Effective JavaScript :第二章
1.熟练掌握闭包
理解闭包要学会三个基本的事实:
①JavaScript允许你引用在当前函数以外定义的变量;
例如:
function makeSandwich(){
var magicIngredient = ‘peanut butter’;
function make(filling){
return magicIngredient + ‘and’ + filling;
}
return make(‘jelly’);
}
makeSandwich(); //‘peanut butter and jelly’
②即使外部函数已经返回,当前函数仍然可以引用在外部函数所定义的变量;
function sandwichMaker(){
var magicIngredient = ‘peanut butter’;
function make(filling){
return magicIngredient + ‘and’+filling;
}
return make;
}
var f = sandwichMaker();
f(‘jelly’);
f(‘bananas’);
f(‘marshmallows’);
f的值为内部的make函数,调用f实际上是调用make函数。
③闭包可以更新外部变量的值。
function box(){
var val = undefined;
return {
set : function(newVal){ val = newVal; },
get : function() { return val; },
type : function(){ return typeof val;}
};
}
val b = box();
b.type();
b.set(98.6);
b.get();
b.type();
该例子产生了一个包含三个闭包的对象,这三个闭包是set、get和type属性。它们共享访问val变量。set闭包更新val的值,随后调用get和type查看更新结果。
3.解决JavaScript缺少块级作用域的方法:
①创建一个嵌套函数并立即调用它来强制创建一个局部作用域:
function wrapElements(a){
var result = [];
for(var i = 0 , n = a.length; i < n ; i ++){
(function(){
var j = i;
result[i] = function(){ return a[j] ; };
})();
}
result result;
}
②将作为形参的局部变量绑定到IIFE并将其值作为实参传入。
使用IIFE来创建局部作用域要小心,因为在函数中包裹代码块可能会导致代码块发生一些微妙的变化。首先,代码块不能包含任何跳出块的break语句和continue语句。因为在函数外使用break和continue是不合法的。其次,如果代码块引用了this或特别的arguments变量,IIFE将会改变它们的含义。
4.匿名函数和命名函数表达式的官方区别在于后者会绑定到与其函数名相同的变量上,该变量将作为该函数内的一个局部变量。命名函数表达式的真正用处是进行调试。
5.在系统中,避免对象污染函数表达式作用域的最好方式是避免任何时候在Object.prototype中添加属性,以及避免任何使用与标准Object.prototype属性同名的局部变量。
6.命名函数表达式会导致很多问题所以不值得使用。
7.编写可移植函数的最好方式是始终避免将函数声明置于局部块或子语句中。如果想编写嵌套函数声明,应该将它置于其父函数的最外层,如果你需要有条件地选择函数,最好的办法就是使用var声明和函数表达式来实现。
function f(){ return ‘global’; }
function test(x){
var g = f , result = [];
if(x){
g = function(){ return‘local’; }
result.push(g());
}
result.push(g());
return result;
}
这消除了内部变量作用域的神秘性。它无条件地作为局部变量被绑定,而仅仅只有赋值语句是有条件地。结果很明确,该函数完全可移植。
8.错误使用eval的方式:
①允许它干扰作用域。
调用eval函数会将参数作为JavaScript程序进行解释。但是该程序运行于调用者的局部作用域中,嵌入到程序的全局变量会被创建为调用程序的局部变量。
function test(x){
eval(‘var y = x ;’ );
return y;
}
test(‘hello’); //‘hello’
保证eval函数不影响外部作用域的一个简单方法是在一个明确的嵌套作用域中运行它。
var y =‘global’;
function test(src){
(function () {eval(src);})();
return y;
}
test (“var y = ‘local’;”); //‘global’
test(“var z = ‘local’;”); //‘global’
9.间接调用eval函数优于直接调用
eval函数具有访问调用它那时的整个作用域的能力。
直接调用eval:
var x = ‘global’;
function test(){
var x = ‘local’;
return eval(‘x’);
}
test(); //‘local’;
间接调用eval:
var x = ‘global’;
function test(){
var x = ‘local’;
var f = eval ;
return f(‘x’) ;
}
test() ;
绑定eval函数到另一个变量名,通过该变量名调用函数会使代码失去对所有局部作用域的访问能力。
编写间接调用eval函数的一种简洁方式是使用表达式序列运算符(,)和一个明显毫无意义的数字字面量。
(0, eval)(src)
Effective JavaScript :第二章的更多相关文章
- JavaScript 数据访问(通译自High Performance Javascript 第二章) [转]
JavaScript 数据访问(通译自High Performance Javascript 第二章) JavaScript 数据访问(翻译自High Performance Javascript ...
- [Effective Java]第二章 创建和销毁对象
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- 如何创建和销毁对象(Effective Java 第二章)
最近有在看Effective Java,特此记录下自己所体会到的东西,写篇博文会更加的加深印象,如有理解有误的地方,希望不吝赐教. 这章主题主要是介绍:何时以及如何创建对象,何时以及如何避免创建对象, ...
- 对于所有对象都通用方法的解读(Effective Java 第二章)
这篇博文主要介绍覆盖Object中的方法要注意的事项以及Comparable.compareTo()方法. 一.谨慎覆盖equals()方法 其实平时很少要用到覆盖equals方法的情况,没有什么特殊 ...
- 你不知道的JavaScript——第二章:this全面解析
1调用位置 调用栈:为了到达当前执行位置所调用的所有函数. function baz(){ //当前调用栈:baz //因此,当前调用位置是全局作用域 console.log('baz'); bar( ...
- JavaScript 第二章总结
Writing real code 设计程序的步骤 First, a high-level design and a flowchart more details Working through th ...
- javascript第二章--变量、作用域和内存问题
① 基本类型和引用类型的值 ② 执行环境及作用域 ③ 垃圾收集
- [Effective JavaScript 笔记]第3章:使用函数--个人总结
前言 这一章把平时会用到,但不会深究的知识点,分开细化地讲解了.里面很多内容在高3等基础内容里,也有很多讲到.但由于本身书籍的篇幅较大,很容易忽视对应的小知识点.这章里的许多小提示都很有帮助,特别是在 ...
- Javascript权威指南——第二章词法结构,第三章类型、值和变量,第四章表达式和运算符,第五章语句
第二章 词法结构 一.HTML并不区分大小写(尽管XHTML区分大小写),而javascript区分大小写:在HTML中,这些标签和属性名可以使用大写也可以使用小写,而在javascript中必须小写 ...
- Javascript高级程序设计读书笔记(第二章)
第二章 在HTML中使用Javascript 2.1<script>元素 延迟脚本(defer = "defer")表明脚本在执行时不会影响页面的构造,脚本会被延迟到 ...
随机推荐
- UIView类绘图出现错误提示
一:问题: Jan 16 15:49:53 CUBOT Band Ⅲ[2082] <Error>: CGContextSetLineWidth: invalid context 0x0. ...
- Qt-剪切板
ClipBoard 存在的意义 进程间数据共享. 方式 Drag And Drop: clipBoard的拖曳方式 app's ClipBoard 缺点 没有权限管理 在Model View中实现Dr ...
- Python反射函数
python里面跟getattr相关的有hasattr,setattr,delattr ,那么我们通过下面的例子,来详细的说说他们的用法. class Xiaorui: def __init__(s ...
- mysql中You can't specify target table for update in FROM clause
使用mysql在删除表中重复记录 delete from user where username in (select user name form(select username from user ...
- jsp页面根据当前时间和定义时间差计算动态倒计时
jsp页面根据当前时间和定义时间差计算动态倒计时http://www.jb51.net/article/74140.htm var maxtime =1000*60; //半个小时,按秒计算,自 ...
- STM32驱动ht1621b显示LCD
这几天在写ht1621b显示LCD的程序,主芯片是Stm32f10的芯片.对于stm32和ht1621b的运用和操作本人是新手,属于赶鸭子上架,通过查看datasheet等资料和网上查看前人写的程序终 ...
- shrio初体验(2)Realm
Realm:域,Shiro从从Realm获取安全数据(如用户.角色.权限),就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法:也需 ...
- find中的-print0和xargs中-0的区别
默认情况下, find 每输出一个文件名, 后面都会接着输出一个换行符 ('\n'), 因此我们看到的 find 的输出都是一行一行的: [bash-4.1.5] ; ls -l total 0 -r ...
- 《C++反汇编与逆向分析技术揭秘》——流程控制语句的识别
if...else...语句 示例: if构成多分支语句 switch 有序线性的switch: 3E82D8位置存放了一个表,标明了要跳转到的地址: 这里的每四字节都标明的是每个case块的首地址: ...
- [SOJ] Ordering Tasks
1940. Ordering Tasks Constraints Time Limit: 1 secs, Memory Limit: 32 MB Description John has n task ...