YouDontKnowJS 学习小结
真正的理解闭包的原理与使用 更加透彻this绑定的四种规则机制
你不知道的JavaScript 人称小黄书,第一次看到这本书名 就想到了一句话 “You know nothing! Jon snow”(你懂得), 翻阅后感觉到很惊艳,分析的很透彻,学习起来也很快,Have fun!
块级作用域
-
if语句
-
for语句
-
with
with(obj) { a = 1; b = 2; c = 3; }
相当于
obj.a = 1;
obj.b = 2;
obj.c = 3; (比较麻烦)
而且用with在对象上创建的块作用域仅仅在with声明中有效
-
try / catch
catch 事实上也会创建一个块作用域,且仅仅在catch内部有效
-
let
-
const
块作用域的用处
- 垃圾回收
- let循环
声明提升
a = 2;
var a;
console.log(a); // 2
这就是声明提升,先有蛋(声明),后有鸡(赋值)
只有声明被提升,赋值或其他逻辑保留在原地
真正的顺序是
var a (未执行前,在编译阶段)
a = 2 (等待执行)
console.log(a)
函数声明会被提升,而函数表达式不会
函数声明,变量声明同时出现(一般不会出现,出现情况是重复声明), 则是 函数优先
作用域闭包
闭包实质: 当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数在当前词法作用域之外执行
将内部函数传递到词法作用域外,他都会有对原始定义作用域的引用,无论在何处执行这个函数都会使用闭包
在定时器,时间监听器,Ajax请求,跨窗口通信,web workers 或者其他任何异步任务,只要使用了
回调函数,实际上都是在使用到了闭包
IIFE:立即执行函数,典型的闭包例子,IIFE会通过声明并立即执行函数创建作用域
经典栗子
for(var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i)
},0);
} // output: 5 5 5 5 5
// setTimeoiut延迟函数会在循环结束之后执行 ,而此时i为5 结果自然为5个5
//利用闭包解决,创建一个块作用域保存一个i的副本即可
@方法1
for(var i = 0; i < 5; i++) {
(function() {
var j = i;
setTimeout(function() {
console.log(j);
},0);
})();
} // output: 0 1 2 3 4
@方法2
for(var i = 0; i < 5; i++) {
(function(j) {
setTimeout(function(