生活随笔
收集整理的這篇文章主要介紹了
Javascript 进阶 作用域 作用域链
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一直覺得Js很強大,由于長期不寫js代碼,最近剛好溫故溫故。
1、Javascript沒有代碼塊作用域的概念,局部作用域是針對函數來說的。
[javascript]?view plaincopy
function?fun()?? {?? ????for(?var?i?=?0?;?i?<?10?;?i++)?? ????{}?? ?????? ????console.log(i);?? ?? ????if(true)?? ????{?? ????????var?b?=?"helloworld";?? ????}?? ????console.log(b);?? }?? fun();??
2、如果不使用var聲明的變量,默認為全局變量
[javascript]?view plaincopy
function?fun02()?? {?? ????a?=?"helloworld";?? ????var?b?=?"welcome";?? }?? fun02();?? console.log(a);??? console.log(b);???
3、Js中的作用域鏈
先看個簡單的例子:只有一個函數對象,函數對象和其它對象一樣,擁有可以通過代碼訪問的屬性和一系列僅供JavaScript引擎訪問的內部屬性。其中一個內部屬性是[[Scope]],由ECMA-262標準第三版定義,該內部屬性包含了函數被創建的作用域中對象的集合,這個集合被稱為函數的作用域鏈,它決定了哪些數據能被函數訪問。
[javascript]?view plaincopy
var?a?=?"hello";?? ?? ??????function?fun04()?? ??????{?? ???????????a?=?"world";?? ????????????var?b?="welcome";?? ??????}??
作用域鏈的圖:
注:圖中省略了,Global Scope中的window,document等,每個函數對象中的arguments,this等均未畫出。
[javascript]?view plaincopy
function?fun03()?? ??????{?? ??????????var?a?=?10;?? ??????????return?function(){?? ??????????????a*=?2?;?? ??????????????return?a?;?? ??????????};?? ??????}?? ?? ??????var?f?=?fun03();?? ??????f();?? ??????var?x?=?f();?? ?????console.log(x);???? ?? ??????var?g?=?fun03();?? ??????var?y?=?g();?? ??????console.log(y);???
觀察上面代碼,存在fun03,f,g三個函數對象。
下面是作用域鏈的圖:
注:每個函數對象一個作用域鏈,這里直接畫在了一起;對于變量的查找,先從鏈的0開始找。
函數對象 f 在代碼中執行了2 次,所以a*2*2 = 40 ; 函數對象 g 在代碼中執行了1次, 所以 a *2 = 20 ;?
4、閉包
上面的例子可以看到,在fun03執行完成后,a的實例并沒有被銷毀,這就是閉包。個人對閉包的理解是:函數執行完成后,函數中的變量沒有被銷毀,被它返回的子函數所引用。
下面以一個特別經典的例子,同時使用作用域鏈解析:
[javascript]?view plaincopy
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.
下面看解決方案:
[javascript]?view plaincopy
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 。
總結
以上是生活随笔為你收集整理的Javascript 进阶 作用域 作用域链的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。