js---开发中对js理解的注意事项

1.在写复杂的 JavaScript 应用之前,充分理解原型链继承的工作方式。

要提防原型链过长带来的性能问题,并知道如何通过缩短原型链来提高性能。

绝对不要扩展内置类型的原型,除非是为了和新的 JavaScript 引擎兼容。

2.为了判断一个对象是否包含自定义属性而不是原型链上的属性, 我们需要使用继承自 Object.prototype 的 hasOwnProperty 方法。hasOwnProperty 是 JavaScript 中唯一一个处理属性但是查找原型链的函数。

3.JavaScript 不会保护 hasOwnProperty 被非法占用,因此如果一个对象碰巧存在这个属性, 就需要使用外部的 hasOwnProperty 函数来获取正确的结果。

4.当检查对象上某个属性是否存在时,hasOwnProperty 是唯一可用的方法。 同时在使用 for in loop 遍历对象时,推荐总是使用 hasOwnProperty 方法, 这将会避免原型对象扩展带来的干扰。

5.一个广泛使用的类库 Prototype 就扩展了原生的 JavaScript 对象。当这个类库被包含在页面中时,不使用 hasOwnProperty 过滤for in 循环难免会出问题。

6.推荐总是使用 hasOwnProperty。不要对代码运行的环境做任何假设,不要假设原生对象是否已经被扩展了。

7.命名函数的赋值表达式

另外一个特殊的情况是将命名函数赋值给一个变量。

var foo = function FUN() {

FUN(); // 正常运行

}

FUN(); // 出错:ReferenceError

FN 函数声明外是不可见的,这是因为我们已经把函数赋值给了 foo; 然而在 FUN内部依然可见。这是由于 JavaScript 的 命名处理 所致, 函数名在函数内总是可见的。

8.闭包是 JavaScript 一个非常重要的特性,这意味着当前作用域总是能够访问外部作用域中的变量。 因为 函数 是 JavaScript 中唯一拥有自身作用域的结构,因此闭包的创建依赖于函数。

9.循环中的闭包

一个常见的错误出现在循环中使用闭包,假设我们需要在每次循环中调用循环序号

for(var i = 0; i < 10; i++) {
    setTimeout(function() {
        console.log(i);  
    }, 1000);
}

上面的代码不会输出数字 0 到 9,而是会输出数字 10 十次。

当 console.log 被调用的时候,匿名函数保持对外部变量 i 的引用,此时 for循环已经结束, i 的值被修改成了 10.

为了得到想要的结果,需要在每次循环中创建变量 i 的拷贝

10.不管它是否有被使用,arguments 对象总会被创建,除了两个特殊情况 - 作为局部变量声明和作为形式参数。

11.有一种情况会显著的影响现代 JavaScript 引擎的性能。这就是使用 arguments.callee

12.显式的 return 表达式将会影响返回结果,但仅限于返回的是一个对象。

function Bar() {

return 2;

}

new Bar(); // 返回新创建的对象Bar

function Test()

this.value = 2;

return {

foo: 1

};

}

new Test(); // 返回的对象Object

13.如果 return 对象的左括号和 return 不在一行上就会出错。

注: 如果不是在赋值语句中,而是在 return 表达式或者函数参数中,{...} 将会作为代码段解析, 而不是作为对象的字面语法解析。如果考虑到 自动分号插入,这可能会导致一些不易察觉的错误。

14.推荐使用匿名包装器(也就是自执行的匿名函数)来创建命名空间。这样不仅可以防止命名冲突, 而且有利于程序的模块化。

另外,使用全局变量被认为是不好的习惯。这样的代码容易产生错误并且维护成本较高。

15.注: JavaScript 中数组不是关联数组。JavaScript 中只有对象 来管理键值的对应关系。但是关联数组是保持顺序的,而对象不是

16.数组:为了更好的性能,推荐使用普通的 for 循环并缓存数组的 length 属性。 使用 for in 遍历数组被认为是不好的代码习惯并倾向于产生错误和导致性能问题。

17.由于 Array 的构造函数在如何处理参数时有点模棱两可(这里的模棱两可指的是数组的两种构造函数语法),因此总是推荐使用数组的字面语法 - [] - 来创建数组。

应该尽量避免使用数组构造函数创建新数组。推荐使用数组的字面语法。它们更加短小和简洁,因此增加了代码的可读性

18.使用 == 被广泛认为是不好编程习惯的主要原因, 由于它的复杂转换规则,会导致难以跟踪的问题。强制类型转换也会带来性能消耗。强烈推荐使用严格等于操作符。如果类型需要转换,应该在比较之前显式的转换, 而不是使用语言本身复杂的强制转换规则。

19.为了检测一个对象的类型,强烈推荐使用 Object.prototype.toString 方法; 因为这是唯一一个可依赖的方式。正如上面表格所示,typeof 的一些返回值在标准文档中并未定义, 因此不同的引擎实现可能不同。除非为了检测一个变量是否已经定义,我们应尽量避免使用 typeof 操作符。

20.instanceof 操作符应该仅仅用来比较来自同一个 JavaScript 上下文的自定义对象。 正如 typeof 操作符一样,任何其它的用法都应该是避免的。

21.在任何情况下我们都应该避免使用 eval 函数。 99.9 % 使用 eval 的场景都有不使用 eval 的解决方案

22.eval 也存在安全问题,因为它会执行任意传给它的代码, 在代码字符串未知或者是来自一个不信任的源时,绝对不要使用 eval 函数。

23.ES5 提示: 在 ECMAScript 5 的严格模式下,undefined 不再是 可写的了。 但是它的名称仍然可以被隐藏,比如定义一个函数名为 undefined

24.JavaScript 中的 undefined 的使用场景类似于其它语言中的 null,实际上 JavaScript 中的 null 是另外一种数据类型。

它在 JavaScript 内部有一些使用场景(比如声明原型链的终结 Foo.prototype = null),但是大多数情况下都可以使用 undefined 来代替。

25.JavaScript 不能正确的处理 return 表达式紧跟换行符的情况, 虽然这不能算是自动分号插入的错误,但这确实是一种不希望的副作用。

26.注: 定时处理不是 ECMAScript 的标准,它们在 DOM (文档对象模型) 被实现。

27.注: setTimeout 的第一个参数是函数对象,一个常犯的错误是这样的 setTimeout(foo(), 1000), 这里回调函数是 foo 的返回值,而不是foo本身。 大部分情况下,这是一个潜在的错误,因为如果函数返回 undefinedsetTimeout 也不会报错。

 28.注: 虽然也可以使用这样的语法 setTimeout(foo, 1000, 1, 2, 3), 但是不推荐这么做,因为在使用对象的属性方法时可能会出错。(注:这里说的是属性方法内,this 的指向错误)

29.绝对不要使用字符串作为 setTimeout 或者 setInterval 的第一个参数, 这么写的代码明显质量很差。当需要向回调函数传递参数时,可以创建一个匿名函数,在函数内执行真实的回调函数。

另外,应该避免使用 setInterval,因为它的定时执行不会被 JavaScript 阻塞。

30.

 
原文地址:https://www.cnblogs.com/xiao-peng-ji/p/11734506.html