JavaScript 调用机制[作用域链及闭包理解]

Javascript 中,由于typescript 的流行和各种框架的帮助,部分前端同事们对初始的作用域链和闭包已经忘了不少,如何理解作用域链及闭包对我们以后的发展肯定有不少的好处。

执行上下文:

执行上下文可以理解为当前代码的运行环境。js 中,运行环境主要包含了全局环境和函数环境。同样上下文也可以分为: 全局上下文和函数上下文。

执行上下文的管理是通过**执行上下文栈(Execution Context Stack)**来管理的,栈一种 LIFO 的数据结构。

执行上下文中的三个属性为: 变量对象,【scope chain】作用域链, 和this指向。 this指向会在下篇文档中讲解。

上下文的生命周期分为: 创建和执行阶段, 创建阶段主要工作是:创建变量对象,建立作用域链,绑定this指向。执行阶段主要是:变量赋值和执行其它代码逻辑。

变量对象:

变量对象是由 js 引擎所创建,在代码中不能直接访问,当进入到一个执行上下文时,变量对象被激活,称为(Activation Object)活动对象。变量对象和活动对象都是指同一个对象,只是处于执行上下文的不同阶段。

在执行上下文的创建阶段会生成变量对象,生成变量对象主要有以下三个过程:

  1. 检索当前上下文中的参数。该过程生成 Arguments 对象,并建立以形参变量名为属性名,形参变量值为属性值的属性;
  2. 检索当前上下文中的函数声明。该过程建立以函数名为属性名,函数所在内存地址引用为属性值的属性;
  3. 检索当前上下文中的变量声明。该过程建立以变量名为属性名,undefined 为属性值的属性(如果变量名跟已声明的形参变量名或函数名相同,则该变量声明不会干扰已经存在的这类属性)。

举个例子:

function foo(a) {
var b = 2;
function c() {}
var d = function() {};

b = 3;
}

foo(1);
此时的AO是:
AO = {
arguments: {
0: 1,
length: 1
},
a: 1,
b: undefined,
c: reference to function c(){},
d: undefined
}

作用域链

作用域链是指由当前上下文和上层上下文的一系列变量对象组成的层级链。它保证了当前执行环境对符合访问权限的变量和函数的有序访问。当访问一个变量时,解释器会首先在当前作用域查找标示符,如果没有找到,就去父作用域找,直到找到该变量的标示符或者不在父作用域中,这就是作用域链的一种好理解的形式。

注意!!!
作用域链和原型继承查找时的区别:如果去查找一个普通对象的属性,但是在当前对象和其原型中都找不到时,会返回undefined;但查找的属性在作用域链中不存在的话就会抛出ReferenceError。

那么作用域链是如何被建立起来的呢?

在Javascript中,存在全局作用域和函数作用域,函数作用域是在函数被声明的时候确定的。
在每一个函数内部都有一个内部属性:[[scope]], 在函数被声明的时候,该函数的 [[scope]] 属性会保存其上层上下文的变量对象,形成包含上层上下文变量对象的层级链。[[scope]] 属性的值是在函数被声明的时候确定的。

当函数被调用的时候,其执行上下文会被创建并入栈。在创建阶段生成其变量对象后,会将该变量对象添加到作用域链的顶端并将 [[scope]] 添加进该作用域链中。而在执行阶段,变量对象会变为活动对象,其相应属性会被赋值。

This 指向

下一篇将详细讲解 this的指向与绑定问题。
先留一个测试题:
var num = 1;
var myObject = {
num: 2,
add: function() {
this.num = 3;
(function() {
console.log(this.num);
this.num = 4;
})();
console.log(this.num);
},
sub: function() {
console.log(this.num)
}
}
myObject.add();
console.log(myObject.num);
console.log(num);
var sub = myObject.sub;
sub();

应该输出什么呢?
欢迎大家关注,点赞!!!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值