作用域和作用域链:

  参考文章 :http://www.cnblogs.com/malinlin/p/6028842.html

        http://www.cnblogs.com/lhb25/archive/2011/09/06/javascript-scope-chain.html

        http://www.zhangyunling.com/?p=134

        https://segmentfault.com/a/1190000000652891

总结: 

  ① js中处处是对象

  ②函数执行时会创建一个执行环境和变量对象

  ③代码在执行环境中运行 变量对象会按照顺序存到作用域链中

  ④执行一次函数就会创建一个新的活动对象,就会有新的作用域链,多个作用域链互不干扰.

  ⑤引用函数不消失,活动变量就一直存在 , 闭包使用完了之后 将引用变量指向null,释放内存.

1. 全局作用域(Global Scope)
  (1)最外层函数和在最外层函数外面定义的变量拥有全局作用域
  (2)所有没有定义直接赋值的变量,自动声明为拥有全局作用域
  (3)所有window对象的属性拥有全局作用域,例如window.name、window.location  如下:定时器里指向的是全局的函数

    setTimeout("C()",1000)==setTimeout("this.C()",1000)

  

 var a = 1;
function B(){
var a = 2;
setTimeout("C()",1000);
setTimeout(C,2000);
function C(){
alert("a="+a);
}
}
function C(){
alert("a="+a);
}
B();

2. 局部作用域(Local Scope) 
  局部作用域一般只在固定的代码片段内可访问到,最常见的例如函数内部

1. 执行环境和活动对象

  函数在执行时 生成执行环境 和 变量对象 ,当代码在一个执行环境中执行时,会创建变量对象的一个作用域链(scope chain)

  执行环境(execution context)定义了变量或者函数有权访问的其他数据,每个执行环境都有一个与之关联的变量对象(variable object),执行环境中定义的变量和函数就保存在这个变量对象中;
  全局执行环境是最外围的一个执行环境,通常被认为是window对象
  执行环境中的所有代码执行完以后,执行环境被销毁,保存在其中的变量和函数也随之销毁;(全局执行环境到应用退出时销毁).

  在闭包,每次执行A函数时,都会生成一个A的活动变量和执行环境,执行完毕以后,A的执行环境销毁,但是活动对象由于被闭包函数引用,所以仍然保留,所以闭包使用完了之后 将引用变量指向null

3. 作用域链(Scope Chain)
   当代码在一个执行环境中执行时,会创建变量对象的一个作用域链(scope chain),作用域链用来指定执行环境有权访问的所有变量和函数的访问顺序;当一个函数创建后,它的作用域链会被创建此函数的作用域中可访问的数据对象填充。

  作用域链的最前端,始终是当前代码执行环境的变量对象,如果这个环境是函数,则其活动对象就是变量对象
  作用域链的下一个变量对象,来自外部包含环境,再下一个变量对象,来自下一个外部包含环境,以此类推直到全局执行环境
  在函数执行过程,根据当前执行环境的作用域链来逐层向外查找变量,并且进行标识符解析

  这些值按照它们出现在函数中的顺序被复制到运行期上下文的作用域链中。 它们共同组成了一个新的对象,叫“活动对象(activation object)”,该对象 包含了函数的所有局部变量、命名参数、参数集合以及this,然后此对象会 被推入作用域链的前端,当运行期上下文被销毁,活动对象也随之销毁。

   在函数执行过程中,没遇到一个变量,都会经历一次标识符解析过程以决定从哪里获取和存储数据。该过程从作用域链头部,也就是从活动对象开始搜索,查找同名的标识符,如果找到了就使用这个标识符对应的变量,如果没找到继续搜索作用域链中的下一个对象,如果搜索完所有对象都未找到,则认为该标识符未定义。函数执行过程中,每个标识符都要经历这样的搜索过程。从作用域链的结构可以看出,在运行期上下文的作用域链中,标识符所在的位置越深,读写速度就会越慢。在编写代码的时候应尽量少使用全局变量,尽可能使用局部变量。一个好的经验法则是:如果一个跨作用域的对象被引用了一次以上,则先把它存储到局部变量里再使用。

闭包:

  1.闭包可以访问函数中的变量。

  2.可以使变量长期保存在内存中,生命周期比较长。但闭包不能滥用,否则会导致内存泄露,影响网页的性能。闭包使用完了后,要立即使用资源,将引用变量指向null。

<script>
function A(){
var x = 1;
return function(){
x++;
console.log(x);
}
}
var m1 = A();//第一次执行A函数
m1();//
m1();//
var m2 = A();//第二次执行A函数
m2();//
m1();//
</script>

1.(为什么连续执行m1的时候,x的值在递增?)
answer:因为m1在引用的活动对象A一直没有释放(想释放的话可以让m1=null),所以x的值一直递增。
2.定义函数m2的时候,为什么x的值重新从1开始了?
answer:因为又一次运行了A函数,生成一个新的A的活动对象,所以m2的作用域链引用的是一个新的x值。
3.m1和m2里面的x为什么是相互独立,各自维持的?
answer:因为在定义m1和m2的时候,分别运行了A函数,生成了两个活动对象,所以,m1和m2的作用域链是指向不同的A的活动对象的。

好的,到这里先回顾一下前面说到的知识点:

  执行环境和变量对象在运行函数时生成
  执行环境中的所有代码执行完以后,执行环境被销毁,保存在其中的变量和函数也随之销毁;(全局执行环境到应用退出时销毁)

闭包常见题目:

  

 function f1(){
    var n=999;
    nAdd=function(){n+=1}
    function f2(){
      alert(n);
    }
    return f2;
  }
  var result=f1();
  result(); //
  nAdd(); //首先在nAdd前面没有使用var关键字,因此nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,
  result(); // 1000

在这段代码中,result实际上就是闭包f2函数。它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。

为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。

这段代码中另一个值得注意的地方,就是"nAdd=function(){n+=1}"这一行,首先在nAdd前面没有使用var关键字,因此nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。

 

闭包中this的指向:

  

var name = "The Window";
var object = {
name : "My Object", getNameFunc : function(){
return function(){
return this.name;
};
}
}; document.write(object.getNameFunc()());//The Window 匿名函数的执行环境具有全局性,因此其this对象通常指向window

JavaScript---闭包和作用域链的更多相关文章

  1. javascript闭包和作用域链

    最近在学习前端知识,看到javascript闭包这里总是云里雾里.于是翻阅了好多资料记录下来本人对闭包的理解. 首先,什么是闭包?看了各位大牛的定义和描述各式各样,我个人认为最容易一种说法: 外部函数 ...

  2. Javascript——闭包、作用域链

    1.闭包:是指有权访问另一个函数作用域中的变量的函数.创建闭包的常见方式:在一个函数内部创建另一个函数. function f(name){ return function(object){ var ...

  3. Javascript中闭包的作用域链

    作用域定义了在当前上下文中能够被访问到的成员,在Javascript中分为全局作用域和函数作用域,通过函数嵌套可以实现嵌套作用域. 闭包一般发生在嵌套作用域中.闭包是JavaScript最强大的特性之 ...

  4. javascript笔记:javascript的关键所在---作用域链

    javascript里的作用域是理解javascript语言的关键所在,正确使用作用域原理才能写出高效的javascript代码,很多javascript技巧也是围绕作用域进行的,今天我要总结一下关于 ...

  5. javascript的关键所在---作用域链

    javascript的关键所在---作用域链 javascript里的作用域是理解javascript语言的关键所在,正确使用作用域原理才能写出高效的javascript代码,很多javascript ...

  6. [ JS 进阶 ] 闭包,作用域链,垃圾回收,内存泄露

    原网址:https://segmentfault.com/a/1190000002778015 1. 什么是闭包? 来看一些关于闭包的定义: 闭包是指有权访问另一个函数作用域中变量的函数 --< ...

  7. JS闭包、作用域链、垃圾回收、内存泄露相关知识小结

    补充: 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 闭包的三个特性: 1.函数嵌套函数 2.函数内部可以引用外部的参数和变量 3.参数和变 ...

  8. JavaScript 中的闭包和作用域链(读书笔记)

    要想理解闭包,应当先理解JavaScript的作用域和作用域链. JavaScript有一个特性被称之为“声明提前(hoisting)”,即JavaScript函数里声明的所有变量(但不涉及赋值)都被 ...

  9. javascript深入浅出图解作用域链和闭包

    一.概要 对于闭包的定义(红宝书P178):闭包就是指有权访问另外一个函数的作用域中的变量的函数. 关键点: 1.闭包是一个函数 2.能够访问另外一个函数作用域中的变量 文章首发地址于sau交流学习社 ...

  10. [译]JavaScript:函数的作用域链

    原文:http://blogs.msdn.com/b/jscript/archive/2007/07/26/scope-chain-of-jscript-functions.aspx 在JavaScr ...

随机推荐

  1. js判断用户的浏览器设备是移动端还是pc端

    最近做的一个网站页面中需要根据用户的访问设备的不同来显示不同的页面样式,主要是判断移动设备还是电脑浏览器访问的. 下面给出js判断处理代码,以作参考. <script type="te ...

  2. css三角形的实现

    实底三角形: <html> <head> <title></title> <style type="text/css"> ...

  3. unity下载文件三(http异步下载)

    异步下载,顾名思义就是不影响你主线程使用客户端的时候,人家在后台搞你的明堂. 直接入主题,既然要下载,首先得请求,请求成功之后进行回调,这就是一个异步过程,异步回调的时间不可控. 1.首先请求下载. ...

  4. OC中NSArray

    #import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { ...

  5. Office 2013 激活工具

    早上装机,顺便装了下Office 2013,界面还是不错的.网上找了下相关的激活工具. 发现还是独木成林做的最好呀,直接把别人的链接给拿过来好了,下载地址 http://pan.baidu.com/s ...

  6. DEV 财务货币格式单元格

    在用友金蝶等财务软件中,经常需要输入货币类型的数据, 那么这种输入框要如何制作呢? 扩展DataGridView 的功能  出自在天空飞翔博客 http://www.cnblogs.com/micha ...

  7. Effective Java 50 Avoid strings where other types are more appropriate

    Principle Strings are poor substitutes for other value types. Such as int, float or BigInteger. Stri ...

  8. Autocomplete:属性介绍、firefox中文支持问题

    如有问题,请前往 http://www.cnblogs.com/dreamowneryong/p/4953911.html 原文评论交流 一,属性介绍 * minChars (Number) 在触发a ...

  9. 【Android】 Android实现录音、播音、录制视频功能

    智能手机操作系统IOS与Android平分天下(PS:WP与其他的直接无视了),而Android的免费招来了一大堆厂商分分向Android示好,故Android可能会有“较好”的前景. Android ...

  10. 问题解决——multimap中统计key的种类

    ================声明================= 本文原创,转载请注明出处和作者,并保持文章的完整性. 本文链接:http://www.cnblogs.com/wlsandwho ...