《javascript模式》第2章 基本技巧 中,讲了一些在前段编程中的一些规范和建议,同时还有一些平常经常忽视且容易踩中的坑。
以下仅是部分内容的摘要和总结,以做备忘用,如有错漏,敬请指出。如需了解更多,可参阅原著,挺不错的书。
1 链式赋值的陷阱
function func(){
var innerVar = globalVar = 20;
}
func();
console.log(typeof globalVar); //输出结果为?
上面最后的输出结果是?相信不少人会毫不犹豫地说undefined,确定?
真相是:number
原因:从右至左操作符的优先级。首先,优先级较高的是表达式b=0,此时b未经声明。表达式的返回值为0,它被赋给var声明的局部变量a,如以下代码所示
var a = (b = 0);
建议:对链式赋值的所以变量都进行声明,再进行赋值
function foo() {
var a, b;
a = b = 20; //都是局部变量
}
2 变量释放时的副作用
隐含全局变量与明确定义的全局变量有细微的不同,不同之处在于能否使用delete操作符撤销变量
- 使用var创建的全局变量(这类变量在函数外部创建),不能删除
- 不使用var创建的隐含全局变量(尽管它是在函数内部创建),可以删除
这表明隐含全局变量严格来讲不是真正的变量,而是全局对象的属性。属性可以通过delete操作符删除,但变量不可以
//定义三个全局变量
var global_var = 1;
global_novar = 2; //反模式
(function(){
global_fromfunc = 3; //反模式
})();
//企图删除
delete global_var; //false
delete global_novar; //true
delete global_fromfunc; //true
//测试删除情况
typeof global_var; //'number'
typeof global_novar; //'undefined'
typeof global_fromfunc; //'undefined'
在ES5 strict模式中,为没有声明的变量赋值会抛出错误
3 for-in的陷阱
var person = {
name: 'casper',
age: 11
};
for(var key in person){
console.log(key);
}
运行下上述代码,毫无意外,输出结果为:
输出:name输出:age
将上述代码稍微修改下又如何呢?
var person = {
name: 'casper',
age: 11
};
Object.prototype.getName = function(){};
for(var key in person){
console.log(key);
}
输出结果变成:
输出:name输出:age输出:getName
建议:不要增加内置对象的原型,除非必要,同时需在团队内进行良好的沟通,确保其他团队成员不会因此而遇到一些奇怪的错误
4 注意eval与new Function之间的差别
- eval()会影响到作用域
- new Function()中的代码将在局部函数空间中运行,因此代码中任何采用var定义的变量不会自动成为全局变量
- 无论在哪里执行Function,它都仅能看到全局作用域
直接看代码示例:
console.log(typeof un); //'undefined'
console.log(typeof deux); //'undefined'
console.log(typeof trois); //'undefined'
var jsstring = "var un = 1; console.log(un);";
eval(jsstring); //logs "1"
jsstring = "var deux = 2; console.log(deux);";
new Function(jstring)(); //logs "2"
jsstring = "var trois = 3; console.log(trois);";
(function(){
eval(jsstring);
})(); //logs "3"
console.log(un); //'number'
console.log(typeof deux); //'number'
console.log(typeof trois); //'undefined'
从上面代码示例可以很清楚地看出前两点,关于第三点,请看下面代码示例:
(function(){
var local = 1;
eval("local = 2; console.log(local);"); //logs 3
console.log(local); //logs 3
})();
(function(){
var local = 1;
new Function("console.log(typeof local);")(); //logs 'undefined'
})();