Javascript 進階 範圍 範圍鏈

來源:互聯網
上載者:User

 

一直覺得Js很強大,由於長期不寫js代碼,最近剛好溫故溫故。

1、Javascript沒有代碼塊範圍的概念,局部範圍是針對函數來說的。

 

        function fun()        {            for( var i = 0 ; i < 10 ; i++)            {}            //如果在Java中i此時應當屬於未聲明的變數,但是Js中i的範圍依然存在            console.log(i);//10            if(true)            {                var b = helloworld;            }            console.log(b);//helloworld        }        fun();

 

 

2、如果不使用var聲明的變數,預設為全域變數

 

        function fun02()        {            a = helloworld;            var b = welcome;        }        fun02();        console.log(a); //     helloworld        console.log(b); //   b is not defined

3、Js中的範圍鏈

 

先看個簡單的例子:只有一個函數對象,函數對象和其它對象一樣,擁有可以通過代碼訪問的屬性和一系列僅供JavaScript引擎訪問的內部屬性。其中一個內部屬性是[[Scope]],由ECMA-262標準第三版定義,該內部屬性包含了函數被建立的範圍中對象的集合,這個集合被稱為函數的範圍鏈,它決定了哪些資料能被函數訪問。

 

  var a = hello;        function fun04()        {             a = world;              var b =welcome;        }
範圍鏈的圖:

 


註:圖中省略了,Global Scope中的window,document等,每個函數對象中的arguments,this等均未畫出。

 

  function fun03()        {            var a = 10;            return function(){                a*= 2 ;                return a ;            };        }        var f = fun03();        f();        var x = f();       console.log(x);  //40        var g = fun03();        var y = g();        console.log(y); //20

觀察上面代碼,存在fun03,f,g三個函數對象。

 

下面是範圍鏈的圖:

註:每個函數對象一個範圍鏈,這裡直接畫在了一起;對於變數的尋找,先從鏈的0開始找。

函數對象 f 在代碼中執行了2 次,所以a*2*2 = 40 ; 函數對象 g 在代碼中執行了1次, 所以 a *2 = 20 ;

4、閉包

上面的例子可以看到,在fun03執行完成後,a的執行個體並沒有被銷毀,這就是閉包。個人對閉包的理解是:函數執行完成後,函數中的變數沒有被銷毀,被它返回的子函數所引用。

下面以一個特別經典的例子,同時使用範圍鏈解析:

 

window.onload = function()        {            var elements = document.getElementsByTagName(li);            for(var i = 0; i < elements.length ; i ++)            {                elements[i].onclick = function()                {                    alert(i);                }            }        }

相信上面的代碼肯定大家都寫過,本意是點擊每個li,列印出它們的索引,可是事實上列印出的都是elements.length。這是為什麼呢?

 

看下上面的簡易的範圍鏈(省略了很多部分,主要是理解),此時每個onclick函數的i,指向的都是 onload 中的i 此時的 i = element.length.

下面看解決方案:

 

 window.onload = function ()        {            var elements = document.getElementsByTagName(li);            for (var i = 0; i < elements.length; i++)            {                (function (n)                {                    elements[n].onclick = function ()                    {                        alert(n);                    }                })(i);            }        }

在onclick函數的外層,包了一層立即執行的函數,所以此時的n指向的 n 是立即執行的,所有都是1~elements.length 。

 

 


 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.