JavaScript 作用域链、闭包、原型和原型链

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39956624/article/details/86476190

作用域链及和标识符解析

每一个JavaScript函数都表示为一个对象, 要确切的说, 是Function对象的一个实例. Function对象同其他对象一样, 拥有可以编程访问的属性, 和一系列不能通过代码访问而仅供JavaScript引擎存取的内部属性. 其中有一个内部属性是[[Scope]].

内部属性[[Scope]]包含了一个函数被创建的作用域中对象的集合。这个集合被称为函数的作用域链。它决定哪些数据将被函数访问。函数作用域中每一个对象被称为一个可变对象.。每个可变对象都以”键值对”的形式存在. 当一个函数创建后, 它的作用域链会被创建此函数的作用域中可访问的数据对象所填充。例如,思考下面的全局函数:

function add(num1,num2){
     var sum = num1 + num2;
     return sum;
}

当函数add()创建时,它的作用域插入了一个对象变量,这个全局对象代表着所有在全局范围内定义的变量。该全局对象包含诸如window、navigator和document等。如下图所示:

函数add的作用域将会在执行时期用到.。假设执行如下代码:

var total = add(5,10);

执行此函数时会创建一个称为执行环境(execution context)的内部对象, 一个执行环境定义了一个函数执行时的环境, 函数每次执行环境都是独一无二的, 所以多次调用同一个函数就会导致创建多个执行环境. 当函数执行完毕, 执行环境就会被销毁。
每个执行环境都有自己的作用域链, 用于解析标识符。当执行环境被创建时, 它的作用域链初始化为当前被运行函数的[[Scope]]属性中的对象。这些值按照它们出现的顺序被复制到执行环境中. 这个过程一旦完成, 一个被称为”活动对象”的新对象就为执行环境创建好了。活动对象作为函数运行时的变量对象。包含所有局部变量, 命名参数, 参数集合以及this。然后此对象被推入作用域链的最前端.。当执行环境被销毁, 活动对象也随之被销毁。

在函数执行过程中, 每遇到一个变量, 都会经历一次标识符解析过程以决定从哪里获取或存储数据, 该过程搜索执行环境的作用域链, 查找同名的标识符, 搜索过程从作用域链头部开始, 也就是当前运行函数的活动对象. 如果找到, 就使用这个标识符对应的变量, 如果没有找到, 继续搜索作用域链中的下一个对象, 那么标识符被视为是未定义的. 在函数执行过程中, 每个标识符都要经历这样的搜索过程. 在前面的代码示例中, 函数访问sum, num1, num2时都会产生搜索过程, 正是这个搜索过程影响了性能。

一个好的经验法则是: 如果某个跨作用域的值被引用一次以上, 那么就把它储存到局部变量. 例如先将全局变量的引用存储在一个局部变量中, 然后使用这个局部变量代替全局变量.

闭包、作用域和内存

猜你喜欢

转载自blog.csdn.net/qq_39956624/article/details/86476190
今日推荐