作用域链与[[scope]]
通过调用 Function 构造函数创建的函数对象,其内部的 [[scope]] 属性引用的作用域链中始终只包含全局对象。
- var aFunction = new Function( a, b, "return a+b" );
aFunction.[[scope]] -> globalObject (在javascript 为 window对象)
通过函数声明①或函数表达式②创建的函数对象,其内部的 [[scope]] 属性引用的则是创建它们的执行环境的作用域链。
①
- function someFunction ( Parameters ) {
-
- do someting...
-
- }
②
- var someFunction = function( Parameters ) {
-
- do something...
-
- }
①创建过程如下
1. 在全局的执行环境中,进行变量实例化,根据声明创造相应函数对象(全局执行环境的[[scope]]只包含全局对象)
2. 将函数的[[scope]]指向只包含全局变量的作用链
参考下图
下面谈谈自己对1、2两步的理解:
1为全局对象添加了属性,通过这个属性可以在全局执行环境中调用someFunction,例如:
- function someFunction(a, b) {
- alert( a + b );
- }
- window.someFunction( 2, 3);
window即全局变量通过someFunction这个属性调用了函数
2使得函数可以通过[[scope]],因为它指向全局对象,调用全局对象中的其他属性和变量,例如:
- window.var1 = "HuJin";
- function anontherFunction() {
- alert(var1);
- }
- anontherFunction();
PS:有必要解释一下2中的“指向”,“指向”的意思是加入其中,也就是将全局变量的对象加入到输入本来的[[scope]]中。举例说明:
- window.var1 = "HuJin";
- function anontherFunction() {
- var1 = "CaoLixiang";
- alert(var1);
- }
- anontherFunction();
所以说“指向”并不是说anotherFunction的作用域发生了替换,而是全局变量被加入到了原来的[[scope]]中,即:
annotherFunction.[[scope]](其中包含 var1 = "CaoLixiang") = annotherFunction的活动对象(其中包含 var1 = "CaoLixiang") + 全局对象(其中包含var1 = "HuJin")
上面弹出“HuJin”的例子中,函数先会寻找活动对象的var1属性——annotherFunction活动对象,寻找未果,然后上诉至全局对象。所以这里反映了闭包的强大功能,可以访问外函数的属性和变量。
②创建过程如下
1.在全局执行环境的变量实例化过程中,会先为全局对象创建一个命名属性。而在计算赋值语句之前,暂时不会创建函数对象,也不会将该函数对象的引用指定给全局对象的命名属性。
2.但是,当计算函数表达式时最终还是会在全局执行环境中创建这个函数对象,而为这个创建的函数对象的 [[scope]] 属性指定的作用域链中仍然只包含全局对象。
3.内部的函数声明或表达式会导致在包含它们的外部函数的执行环境中创建相应的函数对象,因此这些函数对象的作用域链会稍微复杂一些。
最后一部分摘录浩行天下的博客——www.ghsky.com——深入理解javascript闭包(2)的部分内容,作为完结。
函数声明是不会受到with
语句的影响,因为它们的函数对象实在变量实例化阶段创建的,因此此时没有with
语句的影响。但是对于函数表达式就不同了,它们可能在一个with
语句块中执行:
-
- var y = { x: 5 };
- function exampleFuncWith() {
- var z;
-
-
-
- with(y){
-
-
-
-
- z = function() {
-
- }
- }
- }
-
-
- exampleFuncWith();
当exampleFuncWith
函数被调用的时候自然会产生一个新的执行上下文,其中的作用域链包含Activation对象之后紧接着全局对象。当执行到with
语句的时候,会将全局变量y
添加到作用域最前,这时候恰好碰到一个函数表达式的执行。函数表达式执行产生的函数对象其中的[[scope]]
属性被赋值为当前创建其的执行上下文,那么显而易见,由于刚刚所说的,现在的执行上下文中包含y
,且其位置还要在Activation
对象之前,此时作用域链的排列是这样的:y –> Activation –> global object
,因此这个函数表达式就受到with
语句的影响。
当与 with 语句相关的语句块执行结束时,执行环境的作用域得以恢复(y 会被移除),但是已经创建的函数对象z的 [[scope]] 属性所引用的作用域链中位于最前面的仍然是对象 y。
最后依然是用一张图做总结,下图是对例子形象描述:
从图中很容易发现,如果在不存在with
语句时,函数对象的[[scope]]
属性与外层函数(或者全局对象)的执行上下文有着密切的联系,这种联系也就形成了作用域链,建立了内外函数的沟通桥梁,这样也便很容易理解为什么内层函数可以访问外层函数局部变量。
- 大小: 25.4 KB
- 大小: 9 KB
- 大小: 9.1 KB
- 大小: 64.3 KB
分享到:
相关推荐
### 面向对象的JavaScript编程及其Scope处理 #### 一、JavaScript的面向对象特性 JavaScript作为一种弱类型的脚本语言,虽然本质上不是一种面向对象的语言,但我们可以通过巧妙地利用其特性来实现面向对象编程...
本资源围绕的主题是“作用域(Scope)”,这是理解JavaScript中的变量、函数以及代码组织方式的关键概念。"What-is-Scope.pdf.zip"是一个压缩包文件,其中包含了一份详细讲解JavaScript作用域的PDF文档——"What is ...
### 闭包的理解 #### 背景与概念 在探讨闭包之前,我们先来了解几个相关的概念:作用域、变量作用域以及函数的作用域链。...通过理解和运用闭包,开发者可以在JavaScript中实现更复杂的功能和更高效的代码结构。
深入理解JavaScript系列(14):作用域链(Scope Chain) 深入理解JavaScript系列(15):函数(Functions) 深入理解JavaScript系列(16):闭包(Closures) 深入理解JavaScript系列(17):面向对象编程之一般...
### JavaScript闭包详解 #### 一、什么是闭包? 闭包是JavaScript中一个重要的概念,它涉及函数如何访问外部作用域中的变量。虽然官方定义较为复杂:“闭包是...理解和掌握闭包对于深入学习JavaScript编程至关重要。
- **Nested scope**:嵌套作用域的概念,以及如何处理闭包问题。 - **Functions as values**:函数作为值的高级用法,包括高阶函数的概念。 - **Declaration notation**:函数声明与函数表达式的区别。 ##### 3.5 *...
理解函数的原型链和闭包对于深入掌握JavaScript至关重要。 首先,让我们看看函数的定义方式。在JavaScript中,我们可以使用`function`关键字直接定义函数,如`function fn(a, b) {}`。此外,函数也可以通过赋值语句...
首先,理解闭包需要先了解JavaScript的作用域。在JavaScript中,作用域决定了变量的可见性和生命周期。全局作用域中的变量在整个脚本中都可访问,而函数内部声明的变量则属于局部作用域,只能在该函数内部访问。当...
闭包是JavaScript编程中一个核心且关键的概念,尤其对于初学者而言,理解起来可能有些挑战。闭包本质上是一种特殊的作用域,它可以捕获并存储其外部函数作用域内的变量,即使外部函数已经执行完毕。简单来说,闭包...
在深入理解闭包之前,我们需要先了解JavaScript的作用域规则。 1. **作用域**:在JavaScript中,变量的作用域分为两种,全局作用域和局部作用域。全局变量在整个代码中都可访问,而局部变量只在其定义的函数内部...
### JavaScript闭包详解 #### 一、闭包概念与工作机制 **闭包**是JavaScript中最强大的特性之一,它使得函数能够记住并访问其定义时所在的作用域中的变量。要理解和运用闭包,首先需要理解作用域、作用域链以及...
这个压缩包中的"lab-javascript-basic-algorithms-master"可能包含了一系列练习,涵盖了上述知识点,通过实际编写代码来加深理解。通过解决这些练习,学习者能够逐步熟悉JavaScript的语法和常用技巧,为后续更高级的...
在JavaScript编程中,“闭包”是一个非常重要的概念,尤其对于希望深入理解和高效使用JavaScript的开发者来说。简单地说,闭包是一种能够记住并访问其创建时周围环境的函数。这种能力使得闭包能够在函数执行完毕后...
深入理解JavaScript系列(14):作用域链 Scope Chain 深入理解JavaScript系列(15):函数(Functions) 深入理解JavaScript系列(16):闭包(Closures) 深入理解JavaScript系列(17):面向对象编程之一般...
闭包是JavaScript编程中一个重要的概念,它涉及到函数和作用域的交互,是理解JavaScript内存管理的关键。在JavaScript中,每个函数都有自己的作用域,即它能够访问的变量范围。当一个内部函数引用了外部函数的变量时...
闭包是JavaScript编程中一个非常重要的概念,它在函数式编程...理解并熟练运用闭包对于编写高效、可维护的JavaScript代码至关重要。在实际开发中,合理地利用闭包可以提高代码质量,避免全局污染,同时也可以优化性能。
理解作用域和闭包对于编写高效的JavaScript代码至关重要,它们可以帮助你避免变量污染,实现数据封装,以及创建可复用和模块化的代码。同时,掌握这些概念有助于解决一些常见的JavaScript问题,比如变量作用域冲突和...
scope-chains-closures, Javascript作用域链和闭包 workshop 范围链和闭包 workshop正在启动$ npm install -g scope-chains-closures$ scope-chains-closures # or, shorter: sccjs使用箭头
### 闭包作用域 #### 一、JavaScript闭包简介 ...通过理解闭包的作用域和生命周期,开发者可以更好地利用闭包来解决实际问题,并避免潜在的内存管理问题。掌握闭包的使用对于成为一名合格的前端工程师至关重要。