zoukankan      html  css  js  c++  java
  • (转载)Javascript 进阶 作用域 作用域链

    载请标明出处:http://blog.csdn.net/lmj623565791/article/details/25076713

    一直觉得Js很强大,由于长期不写js代码,最近刚好温故温故。

    1、Javascript没有代码块作用域的概念,局部作用域是针对函数来说的。

    [javascript] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. function fun()  
    2. {  
    3.     for( var i = 0 ; i < 10 ; i++)  
    4.     {}  
    5.     //如果在Java中i此时应当属于未声明的变量,但是Js中i的作用域依然存在  
    6.     console.log(i);//10  
    7.   
    8.     if(true)  
    9.     {  
    10.         var b = "helloworld";  
    11.     }  
    12.     console.log(b);//helloworld  
    13. }  
    14. fun();  

    2、如果不使用var声明的变量,默认为全局变量

    [javascript] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. function fun02()  
    2. {  
    3.     a = "helloworld";  
    4.     var b = "welcome";  
    5. }  
    6. fun02();  
    7. console.log(a); //     helloworld  
    8. console.log(b); //   b is not defined  


    3、Js中的作用域链

    先看个简单的例子:只有一个函数对象,函数对象和其它对象一样,拥有可以通过代码访问的属性和一系列仅供JavaScript引擎访问的内部属性。其中一个内部属性是[[Scope]],由ECMA-262标准第三版定义,该内部属性包含了函数被创建的作用域中对象的集合,这个集合被称为函数的作用域链,它决定了哪些数据能被函数访问。

    [javascript] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. var a = "hello";  
    2.   
    3.       function fun04()  
    4.       {  
    5.            a = "world";  
    6.             var b ="welcome";  
    7.       }  

    作用域链的图:


    注:图中省略了,Global Scope中的window,document等,每个函数对象中的arguments,this等均未画出。

    [javascript] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. function fun03()  
    2.       {  
    3.           var a = 10;  
    4.           return function(){  
    5.               a*= 2 ;  
    6.               return a ;  
    7.           };  
    8.       }  
    9.   
    10.       var f = fun03();  
    11.       f();  
    12.       var x = f();  
    13.      console.log(x);  //40  
    14.   
    15.       var g = fun03();  
    16.       var y = g();  
    17.       console.log(y); //20  


    观察上面代码,存在fun03,f,g三个函数对象。

    下面是作用域链的图:

    注:每个函数对象一个作用域链,这里直接画在了一起;对于变量的查找,先从链的0开始找。

    函数对象 f 在代码中执行了2 次,所以a*2*2 = 40 ; 函数对象 g 在代码中执行了1次, 所以 a *2 = 20 ; 

    4、闭包

    上面的例子可以看到,在fun03执行完成后,a的实例并没有被销毁,这就是闭包。个人对闭包的理解是:函数执行完成后,函数中的变量没有被销毁,被它返回的子函数所引用。

    下面以一个特别经典的例子,同时使用作用域链解析:

    [javascript] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. window.onload = function()  
    2.         {  
    3.             var elements = document.getElementsByTagName("li");  
    4.             for(var i = 0; i < elements.length ; i ++)  
    5.             {  
    6.                 elements[i].onclick = function()  
    7.                 {  
    8.                     alert(i);  
    9.                 }  
    10.             }  
    11.   
    12.         }  


    相信上面的代码肯定大家都写过,本意是点击每个li,打印出它们的索引,可是事实上打印出的都是elements.length。这是为什么呢?

    看下上面的简易的作用域链(省略了很多部分,主要是理解),此时每个onclick函数的i,指向的都是 onload 中的i 此时的 i = element.length.

    下面看解决方案:

    [javascript] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. window.onload = function ()  
    2.        {  
    3.            var elements = document.getElementsByTagName("li");  
    4.            for (var i = 0; i < elements.length; i++)  
    5.            {  
    6.                (function (n)  
    7.                {  
    8.                    elements[n].onclick = function ()  
    9.                    {  
    10.                        alert(n);  
    11.                    }  
    12.                })(i);  
    13.            }  
    14.   
    15.        }  


    在onclick函数的外层,包了一层立即执行的函数,所以此时的n指向的 n 是立即执行的,所有都是1~elements.length 。

    ----------------------------------------

    以上原子 摘抄的  (文章开头的链接)

    ----------------------------------------

    其实,关于上面循环中,i获取到的始终是  elements.length的问题,只需要 将 i 的值定义一个变量 存放一下,也可以解决。

  • 相关阅读:
    8-16 不无聊序列 non-boring sequences uva1608
    8-8 Ddfense Line uva1471 优先级队列
    8-12 Erratic Expansion uva12627
    8-4 Fabled Rooks uva11134
    8-10 Coping Books uva714
    8-13 Just Finish it up uva11093
    8-11 Add All uva 10954
    8-2 Building for UN Uva1605
    css定位.py
    处理HTML5视频播放.py
  • 原文地址:https://www.cnblogs.com/Tmc-Blog/p/5073317.html
Copyright © 2011-2022 走看看