《javascript模式》读书笔记:容易踩中的那些坑

简介:

《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之间的差别

  1. eval()会影响到作用域
  2. new Function()中的代码将在局部函数空间中运行,因此代码中任何采用var定义的变量不会自动成为全局变量
  3. 无论在哪里执行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'
})();

相关文章
|
6月前
|
设计模式 缓存 JavaScript
JavaScript 简单实现观察者模式和发布-订阅模式
JavaScript 简单实现观察者模式和发布-订阅模式
32 0
|
4月前
|
前端开发 JavaScript
JavaScript基础知识:JavaScript 中的异步编程有哪些模式?
JavaScript基础知识:JavaScript 中的异步编程有哪些模式?
37 0
|
9月前
|
设计模式 前端开发 JavaScript
|
9月前
|
设计模式 前端开发 JavaScript
|
9月前
|
JavaScript
【常见面试题】JS 发布者、订阅者模式
面试中经常出现问到如何实现JS 发布者、订阅者模式。
76 2
【常见面试题】JS 发布者、订阅者模式
|
5月前
|
JavaScript 程序员 Go
一图看懂编程语言迁移模式:终点站是Python、Go、JS
一图看懂编程语言迁移模式:终点站是Python、Go、JS
|
5月前
|
存储 前端开发 JavaScript
如何使用CSS和JavaScript实施暗模式?
如何使用CSS和JavaScript实施暗模式?
|
6月前
|
移动开发 JavaScript
同样的JS效果,有部分页面生效,有部分页面无效的原因(怪异模式)
同样的JS效果,有部分页面生效,有部分页面无效的原因(怪异模式)
30 0
|
8月前
|
设计模式 开发框架 JavaScript
理解JavaScript 的发布者_订阅者模式
理解JavaScript 的发布者_订阅者模式
47 0
|
9月前
|
存储 设计模式 前端开发