变量声明
变量提升原则:所有的var语句都提前到包含这段逻辑的函数的顶部执行,无论是否真实会被执行
// good use :变量合并 变量和循环之间加空行
function doSomethingWithItems(items) {
var value = 10,
result = value + 10,
i,
len;
for (i = 0, len = items.length; i < len; i++) {
doSomething(items[i]);
}
}
推荐模式:将所有的var语句合并成一个语句,每个变量的初始化 独占一行。赋值运算符应当对齐。保持成本最低,可以让你的代码更短,下载更快
推荐指数: 🌟🌟🌟🌟
函数声明
函数声明会被提到函数调用之前
// bad use
doSomething();
function doSomething() {
console.log("Hello World!");
}
这段代码可以执行,因为javascript引擎会将这段代码解析为:
function doSomething() {
console.log("Hello World!");
}
doSomething();
函数内部的局部函数应该紧接着变量声明之后声明,like this
function doSomethingWithItems(items) {
var i, len,
value = 10,
result = value + 10;
function doSomething(item) {
// code
}
for (i = 0, len = items.length; i < len; i++) {
doSomething(items[i]);
}
}
推荐指数: 🌟🌟🌟🌟🌟
函数调用间隔
// good use
doSomething(item);
// compare example
while (item) {
// code
}
立即调用的函数
匿名函数
本身没有命名的函数,并将匿名函数赋值给变量或者属性
var doSomething = function() {
// code
}
立即执行函数
// bad use
var value = function() {
// function body
return {
message: "Hello!"
}
}();
// good use
var value = (function() {
// function body
return {
message: "Hello!"
}
})()
错误的示例中,value最终被赋值为一个对象,因为函数立即执行了。这种模式的问题在于,会让人误以为将一个匿名函数赋值给了这个变量。如果没有阅读完整段代码,会让人误解,结果是将匿名函数赋给变量还是将函数的执行结果赋值给变量。这种困惑影响代码的可读性。好的使用方法就比较简单明了。
推荐指数: 🌟🌟🌟🌟
严格模式
"use strict":
javascript引擎会将其识别为一条指令,以严格模式来解析代码。这条指令不仅用于全局,也适用于局部
相等
由于javascript弱类型语言,在做计算时 会进行强制类型转换(数据类型相同则不会进行转换)对某些场景来说,是比较成功的,但有些场景我们就会造成意外的结果。发生强制类型转换最常见的场景,使用了类型判断相等运算符 == 和 !=的时候。当要比较的两个值的类型不同时,就会发生类型转换
数字和字符串
数字字符串进行比较,字符串会首先转换成数字,然后进行比较
// 先使用Number()将字符串"5"转为数字,进行比较
console.log(5 == "5"); // true
// 比较数字和十六进制的字符串
console.log(25 == "0x19"); // true
Number()可以正确解析十六进制的格式,会将看起来像十六进制的数字转为十进制,再进行比较
布尔值和数字
布尔值和数字进行比较,布尔值会先转换为数字,再进行比较 true转为1 false转为0
console.log(1 == true); // true
console.log(0 == false); // true
console.log(2 == true); // false
对象和非对象
对象和非对象进行对比,首先调用对象的valueOf方法,得到原始类型值再进行比较,如果没有定义vauleOf(),则调用toString(),之后比较和上述一致
var exampleObj = {
toString: function() {
return "0x19";
}
};
console.log([2] > [11]) // true
tips: 为何此时 '2' > '11',是因为同是字符串时,左边第一位2转为0000 0010(二进制),右边第一位1转为0000 0001(二进制),对比按照后面的位置一一对比
null undefined
在 == 的情况下 null ==undefined 是成立的
所以建议 无论何时使用 === 和 !==
eval
eval()的参数是一个字符串,eval()会将传入的字符串当做代码执行。通用原则是,严禁使用Function,别无他法时使用eval()。setTimeout和setInterval可以使用,但不要用字符串形式而要用函数,由于eval有先天的安全漏洞,所以es5严格模式下对于eval() 有着严格限制,禁止在一个封闭的作用域中使用它创建新变量或者新函数。这条限制,可以使我们在没有其他方式时,也可以使用eval,例如回调中解析json
原始包装类型
javascript有3种原始包装类型:String、Boolean和Number。每种类型都代表全局作用域中的一个构造函数,并表示各自对应的原始值的对象。原始包装类型的主要作用是让原始值具有对象般的行为
// 尽管name是字符串,是原始类型不是对象,但是可以使用toUpperCase
var name = "etong";
console.log(name.toUpperCase());
javascript引擎会创建String类型的新实例,紧跟着就会被销毁,当再次需要的时候 就会再次创建另外一个实例。like this
var name = "etong";
name.author = "duomi";
console.log(name.author); // undefined
这样做会引起开发者的思路在原始值和对象之间反复横跳,增加出bug概率
// bad use
var name = new String("etong");
var author = new Boolean(true);
var count = new Number(10);
推荐指数: 🌟🌟🌟