作用域与作用域链
- 作用域
- 作用域为可访问变量,对象,函数的集合,即变量可用范围;
- 局部作用域:变量在函数内声明,变量为局部作用域,只能在函数内部访问;
- 变量在函数外定义,即为全局变量。全局变量有 全局作用域,网页中所有脚本和函数均可使用;
- JavaScript 变量生命周期在它声明时初始化。局部变量在函数执行完毕后销毁。全局变量在页面关闭后销毁。
- 作用域链
- 访问某个变量时,一层一层的沿着父元素往上找,找到就停止,如果最后没找到就抛出错误;
- active object(AO)
- AO是临时创建的活动对象,该对象包含了函数的所有局部变量,参数,以及this,当执行上下文的时候,就会被销毁,活动也会被销毁;
<script>
let num = 10;
function addNum() {
let num = 0;
num++;
console.log(num);
}
addNum();
console.log(num);
</script>
以上代码执行过程:
- V8引擎解析js原理
闭包的构成及应用场景
- 闭包作用域
<script>
function outer() {
let a1 = 0;
let a2 = 1;
return function inner() {
return a1;
}
}
function testClosure() {
let getInnerData = outer();
console.dir(getInnerData);
}
testClosure();
</script>
- 闭包的使用场景
- 防抖、节流
- 用闭包模拟私有方法
let Counter = (function() { let privateCounter = 0; //私有方法 function change(val) { privateCounter += val; } return { increment: function(val) { change(val); }, decrement: function(val) { change(-val); }, value: function() { return privateCounter; } } })(); console.log(Counter.value()) console.log(Counter.increment(1)) console.log(Counter.increment(1)) console.log(Counter.value()) //打印出0和2
let makeCounter = function() {
let privateCounter = 0;
//私有方法
function change(val) {
privateCounter += val;
}
return {
increment: function(val) {
change(val);
},
decrement: function(val) {
change(-val);
},
value: function() {
return privateCounter;
}
}
};
var Counter1 = makeCounter();
var Counter2 = makeCounter();
console.log(Counter1.value());
Counter1.increment(1);
Counter1.increment(1);
console.log(Counter1.value());
console.log(Counter2.value());
//打印出0 2 0
原因:每个闭包引用各自词法作用域的变量,实现数据的隐藏和封装;
闭包性能考量
闭包子处理速度和内存消耗方面对脚本性能有负面影响;