`
caolixiang
  • 浏览: 8015 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

理解闭包_javascript[[scope]]

    博客分类:
  • Js
阅读更多

作用域链与[[scope]]

通过调用 Function 构造函数创建的函数对象,其内部的 [[scope]] 属性引用的作用域链中始终只包含全局对象。 

 

Js代码 
  1. var aFunction = new Function( a, b, "return a+b" );  

aFunction.[[scope]] -> globalObject (在javascript 为 window对象)

 

通过函数声明①或函数表达式②创建的函数对象,其内部的 [[scope]] 属性引用的则是创建它们的执行环境的作用域链。

 

Js代码 
  1. function someFunction ( Parameters ) {  
  2.   
  3.         do someting...  
  4.   
  5. }  

 

Js代码 
  1. var someFunction = function( Parameters ) {  
  2.   
  3.         do something...  
  4.   
  5. }  

 

①创建过程如下

1. 在全局的执行环境中,进行变量实例化,根据声明创造相应函数对象(全局执行环境的[[scope]]只包含全局对象)

2. 将函数的[[scope]]指向只包含全局变量的作用链

 

参考下图

 
下面谈谈自己对1、2两步的理解:

1为全局对象添加了属性,通过这个属性可以在全局执行环境中调用someFunction,例如:

Js代码 
  1. function someFunction(a, b) {  
  2.             alert( a + b );  
  3.     }  
  4. window.someFunction( 2, 3);  

window即全局变量通过someFunction这个属性调用了函数

 

2使得函数可以通过[[scope]],因为它指向全局对象,调用全局对象中的其他属性和变量,例如:

Js代码 
  1. window.var1 = "HuJin";  
  2. function anontherFunction() {  
  3.      alert(var1);  
  4. }  
  5. anontherFunction();  


PS:有必要解释一下2中的“指向”,“指向”的意思是加入其中,也就是将全局变量的对象加入到输入本来的[[scope]]中。举例说明:

Js代码 
  1. window.var1 = "HuJin";  
  2.  function anontherFunction() {  
  3.       var1 = "CaoLixiang";  
  4.       alert(var1);  
  5.  }  
  6. 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语句块中执行:

Js代码 
  1. /* create a global variable - y - that refers to an object:- */  
  2. var y = { x: 5 }; // object literal with an - x - property  
  3. function exampleFuncWith() {  
  4.     var z;  
  5.     /* Add the object referred to by the global variable - y - to the 
  6.        front of he scope chain:- 
  7.     */  
  8.     with(y){  
  9.         /* evaluate a function expression to create a function object 
  10.            and assign a reference to that function object to the local 
  11.            variable - z - :- 
  12.         */  
  13.         z = function() {  
  14.             // inner function expression body;  
  15.         }  
  16.     }  
  17. }  
  18.    
  19. /* execute the - exampleFuncWith - function:- */  
  20. 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编程及其Scope处理 #### 一、JavaScript的面向对象特性 JavaScript作为一种弱类型的脚本语言,虽然本质上不是一种面向对象的语言,但我们可以通过巧妙地利用其特性来实现面向对象编程...

    What-is-Scope.pdf.zip_javascript

    本资源围绕的主题是“作用域(Scope)”,这是理解JavaScript中的变量、函数以及代码组织方式的关键概念。"What-is-Scope.pdf.zip"是一个压缩包文件,其中包含了一份详细讲解JavaScript作用域的PDF文档——"What is ...

    闭包的理解

    ### 闭包的理解 #### 背景与概念 在探讨闭包之前,我们先来了解几个相关的概念:作用域、变量作用域以及函数的作用域链。...通过理解和运用闭包,开发者可以在JavaScript中实现更复杂的功能和更高效的代码结构。

    深入理解JavaScript系列

    深入理解JavaScript系列(14):作用域链(Scope Chain) 深入理解JavaScript系列(15):函数(Functions) 深入理解JavaScript系列(16):闭包(Closures) 深入理解JavaScript系列(17):面向对象编程之一般...

    javascript闭包详解

    ### JavaScript闭包详解 #### 一、什么是闭包? 闭包是JavaScript中一个重要的概念,它涉及函数如何访问外部作用域中的变量。虽然官方定义较为复杂:“闭包是...理解和掌握闭包对于深入学习JavaScript编程至关重要。

    Eloquent_JavaScript(JavaScript编程精解)第二版 英文版

    - **Nested scope**:嵌套作用域的概念,以及如何处理闭包问题。 - **Functions as values**:函数作为值的高级用法,包括高阶函数的概念。 - **Declaration notation**:函数声明与函数表达式的区别。 ##### 3.5 *...

    深度探讨javascript函数的原型链和闭包

    理解函数的原型链和闭包对于深入掌握JavaScript至关重要。 首先,让我们看看函数的定义方式。在JavaScript中,我们可以使用`function`关键字直接定义函数,如`function fn(a, b) {}`。此外,函数也可以通过赋值语句...

    javascript里的闭包是什么 什么是闭包.zip

    首先,理解闭包需要先了解JavaScript的作用域。在JavaScript中,作用域决定了变量的可见性和生命周期。全局作用域中的变量在整个脚本中都可访问,而函数内部声明的变量则属于局部作用域,只能在该函数内部访问。当...

    揭开Javascript闭包的真实面目

    闭包是JavaScript编程中一个核心且关键的概念,尤其对于初学者而言,理解起来可能有些挑战。闭包本质上是一种特殊的作用域,它可以捕获并存储其外部函数作用域内的变量,即使外部函数已经执行完毕。简单来说,闭包...

    JS 闭包的理解

    在深入理解闭包之前,我们需要先了解JavaScript的作用域规则。 1. **作用域**:在JavaScript中,变量的作用域分为两种,全局作用域和局部作用域。全局变量在整个代码中都可访问,而局部变量只在其定义的函数内部...

    javascript闭包

    ### JavaScript闭包详解 #### 一、闭包概念与工作机制 **闭包**是JavaScript中最强大的特性之一,它使得函数能够记住并访问其定义时所在的作用域中的变量。要理解和运用闭包,首先需要理解作用域、作用域链以及...

    旨在学习基本JS算法(变量、循环等...)的练习_JavaScript_下载.zip

    这个压缩包中的"lab-javascript-basic-algorithms-master"可能包含了一系列练习,涵盖了上述知识点,通过实际编写代码来加深理解。通过解决这些练习,学习者能够逐步熟悉JavaScript的语法和常用技巧,为后续更高级的...

    javascript闭包高级教程

    在JavaScript编程中,“闭包”是一个非常重要的概念,尤其对于希望深入理解和高效使用JavaScript的开发者来说。简单地说,闭包是一种能够记住并访问其创建时周围环境的函数。这种能力使得闭包能够在函数执行完毕后...

    深入理解JavaScript系列(.chm)

    深入理解JavaScript系列(14):作用域链 Scope Chain 深入理解JavaScript系列(15):函数(Functions) 深入理解JavaScript系列(16):闭包(Closures) 深入理解JavaScript系列(17):面向对象编程之一般...

    前端与移动开发:js对闭包的深入理解.docx

    闭包是JavaScript编程中一个重要的概念,它涉及到函数和作用域的交互,是理解JavaScript内存管理的关键。在JavaScript中,每个函数都有自己的作用域,即它能够访问的变量范围。当一个内部函数引用了外部函数的变量时...

    闭包问题html

    闭包是JavaScript编程中一个非常重要的概念,它在函数式编程...理解并熟练运用闭包对于编写高效、可维护的JavaScript代码至关重要。在实际开发中,合理地利用闭包可以提高代码质量,避免全局污染,同时也可以优化性能。

    理解Javascript_15_作用域分配与变量访问规则,再送个闭包

    理解作用域和闭包对于编写高效的JavaScript代码至关重要,它们可以帮助你避免变量污染,实现数据封装,以及创建可复用和模块化的代码。同时,掌握这些概念有助于解决一些常见的JavaScript问题,比如变量作用域冲突和...

    scope-chains-closures, Javascript作用域链和闭包 workshop.zip

    scope-chains-closures, Javascript作用域链和闭包 workshop 范围链和闭包 workshop正在启动$ npm install -g scope-chains-closures$ scope-chains-closures # or, shorter: sccjs使用箭头

    闭包作用域

    ### 闭包作用域 #### 一、JavaScript闭包简介 ...通过理解闭包的作用域和生命周期,开发者可以更好地利用闭包来解决实际问题,并避免潜在的内存管理问题。掌握闭包的使用对于成为一名合格的前端工程师至关重要。

Global site tag (gtag.js) - Google Analytics