前言
今天是对作用域链以及闭包的一个整理,小编之前的相关文章感觉不够细致,所以今天还是再次系统的整理一下,为面试做好准备。
两种作用域
再开始今天的分享之前,我们先来了解一下两种作用域。
-
静态作用域
函数的作用域在函数定义的时候就决定了,我们的js就是采用的静态作用域
-
动态作用域
函数的作用域在函数调用的时候去决定的。
var value = 1;
function foo() {
console.log(value);
}
function bar() {
var value = 2;
foo();
}
bar(); // 1
我们直接上一个实例,看一下输出结果,可能有些人按照作用域链惯例的思想,foo函数在bar()中执行,自己未找到value,然后依据作用域链往调用自己的bar函数去找,诶嘿输出2,这是对作用域链一个很错误的理解(小编后面会细细讲到)。
按照我们作用域的理解来,foo()执行,未找到value然后去函数定义的地方往上层去找,这才是他正真的作用域链,所以该题输出1.
作用域链
我们前面介绍到了执行上下文,执行上下文的三部分就是对象、作用域链、this。
我们上面说到了js是静态作用域,所以函数作用域链[[scope]]的产生是在函数定义的 时候。
function foo() {
function bar() {
...
}
}
// 定义内部属性
foo.[[scope]] = [
globalContext.GO
];
bar.[[scope]] = [
fooContext.AO,
globalContext.GO
];
函数定义即会给内部属性[[scope]]赋值定义他的作用域链(全局作用域链我们简称GO,函数称为AO),那么具体执行过程理解了jiu,这边就不啰嗦了。
闭包
之前小编有一篇关于闭包的文章,但是这边还是写上一下,简单的理解就是嵌套函数被返回在外部执行,他的那么它会保留父级函数作用域链不被销毁,这边就放一个简单的闭包应用吧
function makeAdder(x) {
let a = '外部函数变量'
return function(y) {
return x + y + a;
};
}
var add5 = makeAdder(5);
var add10 = makeAdder(10);
console.log(add5(2)); // '7外部函数变量'
console.log(add10(2)); // '12外部函数变量'
总结
今天简单的总结了一下作用域链和闭包,下一期总结一下原型以及继承(this、call、apply、bind小编之前的文章有写这边就后续不在总结)