成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

深入理解JavaScript作用域和作用域鏈

開發 前端
作用域是JavaScript最重要的概念之一,想要學好JavaScript就需要理解JavaScript作用域和作用域鏈的工作原理。今天這篇文章對JavaScript作用域和作用域鏈作簡單的介紹,希望能幫助大家更好的學習JavaScript。

作用域是JavaScript最重要的概念之一,想要學好JavaScript就需要理解JavaScript作用域和作用域鏈的工作原理。今天這篇文章對JavaScript作用域和作用域鏈作簡單的介紹,希望能幫助大家更好的學習JavaScript。

51CTO推薦專題:JavaScript入門

JavaScript作用域

任何程序設計語言都有作用域的概念,簡單的說,作用域就是變量與函數的可訪問范圍,即作用域控制著變量與函數的可見性和生命周期。在JavaScript中,變量的作用域有全局作用域和局部作用域兩種。

1. 全局作用域(Global Scope)

在代碼中任何地方都能訪問到的對象擁有全局作用域,一般來說一下幾種情形擁有全局作用域:

(1)最外層函數和在最外層函數外面定義的變量擁有全局作用域,例如:

  1. var authorName="山邊小溪";  
  2. function doSomething(){  
  3.     var blogName="夢想天空";  
  4.     function innerSay(){  
  5.         alert(blogName);  
  6.     }  
  7.     innerSay();  
  8. }  
  9. alert(authorName); //山邊小溪  
  10. alert(blogName); //腳本錯誤  
  11. doSomething(); //夢想天空  
  12. innerSay() //腳本錯誤 

(2)所有末定義直接賦值的變量自動聲明為擁有全局作用域,例如:

  1. function doSomething(){  
  2.     var authorName="山邊小溪";  
  3.     blogName="夢想天空";  
  4.     alert(authorName);  
  5. }  
  6. alert(blogName); //夢想天空  
  7. alert(authorName); //腳本錯誤 

變量blogName擁有全局作用域,而authorName在函數外部無法訪問到。

(3)所有window對象的屬性擁有全局作用域

一般情況下,window對象的內置屬性都都擁有全局作用域,例如window.name、window.location、window.top等等。

1. 局部作用域(Local Scope)

和全局作用域相反,局部作用域一般只在固定的代碼片段內可訪問到,最常見的例如函數內部,所有在一些地方也會看到有人把這種作用域成為函數作用域,例如下列代碼中的blogName和函數innerSay都只擁有局部作用域。

  1. function doSomething(){  
  2.     var blogName="夢想天空";  
  3.     function innerSay(){  
  4.         alert(blogName);  
  5.     }  
  6.     innerSay();  
  7. }  
  8. alert(blogName); //腳本錯誤  
  9. innerSay(); //腳本錯誤 

作用域鏈(Scope Chain)

在JavaScript中,函數也是對象,實際上,JavaScript里一切都是對象。函數對象和其它對象一樣,擁有可以通過代碼訪問的屬性和一系列僅供JavaScript引擎訪問的內部屬性。其中一個內部屬性是[[Scope]],由ECMA-262標準第三版定義,該內部屬性包含了函數被創建的作用域中對象的集合,這個集合被稱為函數的作用域鏈,它決定了哪些數據能被函數訪問。

當一個函數創建后,它的作用域鏈會被創建此函數的作用域中可訪問的數據對象填充。例如定義下面這樣一個函數:

  1. function add(num1,num2) {  
  2.     var sum = num1 + num2;  
  3.     return sum;  

在函數add創建時,它的作用域鏈中會填入一個全局對象,該全局對象包含了所有全局變量,如下圖所示(注意:圖片只例舉了全部變量中的一部分):

 

JavaScript作用域鏈

 

函數add的作用域將會在執行時用到。例如執行如下代碼:

  1. var total = add(5,10); 

執行此函數時會創建一個稱為“運行期上下文(execution context)”的內部對象,運行期上下文定義了函數執行時的環境。每個運行期上下文都有自己的作用域鏈,用于標識符解析,當運行期上下文被創建時,而它的作用域鏈初始化為當前運行函數的[[Scope]]所包含的對象。

這些值按照它們出現在函數中的順序被復制到運行期上下文的作用域鏈中。它們共同組成了一個新的對象,叫“活動對象(activation object)”,該對象包含了函數的所有局部變量、命名參數、參數集合以及this,然后此對象會被推入作用域鏈的前端,當運行期上下文被銷毀,活動對象也隨之銷毀。新的作用域鏈如下圖所示:

 

JavaScript作用域鏈

 

在函數執行過程中,沒遇到一個變量,都會經歷一次標識符解析過程以決定從哪里獲取和存儲數據。該過程從作用域鏈頭部,也就是從活動對象開始搜索,查找同名的標識符,如果找到了就使用這個標識符對應的變量,如果沒找到繼續搜索作用域鏈中的下一個對象,如果搜索完所有對象都未找到,則認為該標識符未定義。函數執行過程中,每個標識符都要經歷這樣的搜索過程。

作用域鏈和代碼優化

從作用域鏈的結構可以看出,在運行期上下文的作用域鏈中,標識符所在的位置越深,讀寫速度就會越慢。如上圖所示,因為全局變量總是存在于運行期上下文作用域鏈的最末端,因此在標識符解析的時候,查找全局變量是最慢的。所以,在編寫代碼的時候應盡量少使用全局變量,盡可能使用局部變量。一個好的經驗法則是:如果一個跨作用域的對象被引用了一次以上,則先把它存儲到局部變量里再使用。例如下面的代碼:

  1. function changeColor(){  
  2.     document.getElementById("btnChange").onclick=function(){  
  3.         document.getElementById("targetCanvas").style.backgroundColor="red";  
  4.     };  

這個函數引用了兩次全局變量document,查找該變量必須遍歷整個作用域鏈,直到最后在全局對象中才能找到。這段代碼可以重寫如下:

  1. function changeColor(){  
  2.     var doc=document;  
  3.     doc.getElementById("btnChange").onclick=function(){  
  4.         doc.getElementById("targetCanvas").style.backgroundColor="red";  
  5.     };  

這段代碼比較簡單,重寫后不會顯示出巨大的性能提升,但是如果程序中有大量的全局變量被從反復訪問,那么重寫后的代碼性能會有顯著改善。

改變作用域鏈

函數每次執行時對應的運行期上下文都是獨一無二的,所以多次調用同一個函數就會導致創建多個運行期上下文,當函數執行完畢,執行上下文會被銷毀。每一個運行期上下文都和一個作用域鏈關聯。一般情況下,在運行期上下文運行的過程中,其作用域鏈只會被 with 語句和 catch 語句影響。

with語句是對象的快捷應用方式,用來避免書寫重復代碼。例如:

  1. function initUI(){  
  2.     with(document){  
  3.         var bd=body,  
  4.             links=getElementsByTagName("a"),  
  5.             i=0,  
  6.             len=links.length;  
  7.         while(i < len){  
  8.             update(links[i++]);  
  9.         }  
  10.         getElementById("btnInit").onclick=function(){  
  11.             doSomething();  
  12.         };  
  13.     }  

這里使用width語句來避免多次書寫document,看上去更高效,實際上產生了性能問題。

當代碼運行到with語句時,運行期上下文的作用域鏈臨時被改變了。一個新的可變對象被創建,它包含了參數指定的對象的所有屬性。這個對象將被推入作用域鏈的頭部,這意味著函數的所有局部變量現在處于第二個作用域鏈對象中,因此訪問代價更高了。如下圖所示:

 

JavaScript作用域鏈

 

因此在程序中應避免使用with語句,在這個例子中,只要簡單的把document存儲在一個局部變量中就可以提升性能。

另外一個會改變作用域鏈的是try-catch語句中的catch語句。當try代碼塊中發生錯誤時,執行過程會跳轉到catch語句,然后把異常對象推入一個可變對象并置于作用域的頭部。在catch代碼塊內部,函數的所有局部變量將會被放在第二個作用域鏈對象中。示例代碼:

  1. try{  
  2.     doSomething();  
  3. }catch(ex){  
  4.     alert(ex.message); //作用域鏈在此處改變  

請注意,一旦catch語句執行完畢,作用域鏈機會返回到之前的狀態。try-catch語句在代碼調試和異常處理中非常有用,因此不建議完全避免。你可以通過優化代碼來減少catch語句對性能的影響。一個很好的模式是將錯誤委托給一個函數處理,例如:

  1. try{  
  2.     doSomething();  
  3. }catch(ex){  
  4.     handleError(ex); //委托給處理器方法  

優化后的代碼,handleError方法是catch子句中唯一執行的代碼。該函數接收異常對象作為參數,這樣你可以更加靈活和統一的處理錯誤。由于只執行一條語句,且沒有局部變量的訪問,作用域鏈的臨時改變就不會影響代碼性能了。

原文:http://www.cnblogs.com/lhb25/

【編輯推薦】

  1. JavaScript設計模式深入分析
  2. JavaScript有關的10個秘密和怪癖
  3. 10個頂級Web移動開發JavaScript框架推薦
  4. JavaScript入門之語言基礎
  5. 7個優秀的JavaScript資源推薦
責任編輯:陳貽新 來源: 夢想天空
相關推薦

2019-03-13 08:00:00

JavaScript作用域前端

2021-03-09 08:35:51

JSS作用域前端

2017-09-14 13:55:57

JavaScript

2011-05-12 18:26:08

Javascript作用域

2011-04-18 09:31:35

JavaScript

2021-03-16 22:25:06

作用域鏈作用域JavaScript

2021-03-17 08:39:24

作用域作用域鏈JavaScript

2021-03-09 08:50:58

JavaScript前端作用域

2013-09-05 10:07:34

javaScript變量

2021-06-02 07:02:42

js作用域函數

2021-12-06 07:15:48

Javascript作用域閉包

2016-12-19 11:10:32

JavaScript變量作用域

2009-12-09 14:04:45

PHP include

2010-09-25 16:10:09

添加DHCP作用域

2012-01-05 15:07:11

JavaScript

2015-07-21 13:39:58

Javascript作用域

2015-08-18 13:42:42

js作用域鏈變量

2015-11-26 13:11:24

javascript原型鏈作用域

2021-06-10 18:11:02

Cors跨域Web開發Cors

2021-02-17 11:25:33

前端JavaScriptthis
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日批免费观看 | 国产一级免费在线观看 | 久久精品久久精品久久精品 | 国产精品精品久久久久久 | 日韩国产中文字幕 | 国产精品视频导航 | 亚洲精品成人网 | 国产精品a久久久久 | 国产在线区 | 亚洲日韩中文字幕一区 | 精品一区二区久久久久久久网精 | 性色综合| 亚洲视频在线观看一区二区三区 | 日韩成人影院在线观看 | 蜜月aⅴ国产精品 | 手机在线观看av | 欧美精品久久久 | 国产成人99久久亚洲综合精品 | 国产精品电影网 | 免费骚视频 | 欧美一级免费 | 欧美激情综合色综合啪啪五月 | 操人网站 | 欧美自拍视频 | 在线中文字幕第一页 | 欧美日韩一区二区在线 | 亚洲欧美国产一区二区三区 | 麻豆精品国产91久久久久久 | 欧美日韩三级 | 国产精品久久久久aaaa九色 | 美国黄色毛片 | 成人午夜高清 | 91人人在线| 日日操夜夜操天天操 | 精品欧美| 欧美精品福利视频 | 激情婷婷成人 | 国产成人91视频 | 91综合网| 国产精品美女 | 中文一级片 |