javascript作用域和作用域鏈詳解
阿新 • • 發佈:2022-01-24
目錄
- 一、的作用域
- 1、全域性作用域
- 2、區域性作用域
- 二、script的作用域鏈
- 三、作用域鏈和優化
- 四、改變作用域鏈
- 1、with語法改變作用域鏈
- 2、catch語法
- 總結
一、javascript的作用域
1、全域性作用域
1、最外層函式和最外層函式定義的變數 var age = 20 function func1() { var sex = "男" function func2() { console.log("hello func2") } func2() } console.log(age) //20 console.log(func1) //正常執行 console.log(func2) //報錯 console.log(sex) //報錯
2、所有未直接宣告的變數,直接賦值為全域性變www.cppcns.com量 function func1() { var age = 20 sex = "男" } func1() console.log(sex) //男 console.log(age) //報錯
3、window物件上面的屬性具有全域性作用域 function func1() { var age = 20 sex = "男" console.log(top) //window.... } func1() console.log(sex) //"男" console.log(top) //window....
2、區域性作用域
和全域性作用域相反,區域性作用域只在函式內部可以訪問到。function func1() { var age = 20 func1() function func1() { console.log("func1") }}func1()和全域性作用域相反,區域性作用域只在函式內部可以訪問到。 function func1() { var age = 20 func1() function func1() { console.log("func1") } } func1()
二、javascript的作用域鏈
函式也是物件,在函式內部存在一個屬性[[scope]],該屬性包含可以訪問屬性的集合。決定了哪些屬性在函式中可以訪問到。
下面我們以一個函式的例子來詳細解說一下,函式作用域鏈。 1、在函式函式創建出來時。程式碼如下所示 function add(num1,num2) { return num1 + num2 }
函式初始化時,會將自己的作用域鏈中放入全域性變數
var total = add(10,20) 這裡是函式執行時,當執行時會建立一個新的物件放入作用域鏈中,這個物件中包括 arguments,形參,this,以及返回值。
active object是活躍物件,是函式執行時建立的物件,然後scope chain類似於棧結構,函式執行前壓入棧中,函式執行結束就從棧中彈出。函式訪問屬性的過程就是沿著scope chain從上往下一次查客棧找。
三、作用域鏈和優化
從上面的例子中,我們可以看出,訪問全域性作用域是最慢的,因為需要依次從上往下進行查詢,應當儘可能少的使用全域性變數,應該儘可能使用區域性變數。如果在函式
中,使用多次全域性變數,我們可以RMWZS將全域性變數轉化為區域性變數,然後在使用區域性變數。
function changeColor(){ document.getElementById("btnChange").onclick=function(){ document.getElementById("targetCanvas").style.backgroundColor="red"; }; } 上面程式碼我們使用了兩次document,但是document作為全域性變數,此時我們應該將其轉化為區域性變數來使用,所以下面為轉化後的程式碼。 function changeColor(){ var doc=document; doc.getElementById("btnChange").onclick=function(){ doc.getElementById("targetCanvas").style.backgroundColor="red"; }; }
四、改變作用域鏈
1、with語法改變作用域鏈
with語法的作用就是為了解決程式碼重寫問題,是物件快捷書寫方式,但是這麼好的方式,為什麼不大力推廣使用呢?因為效能存在一些問題。function initUI(){ with(document){ vaRMWZSr bd=body,links=getElementsByTagName("a"),i=0,len=links.length; while(i < len){ update(links[i++]); } getElementById("btnInit").onclick=function(){ doSomething(); }; }}這裡使用with語法省略了document。with語法的作用就是為了解決程式碼重寫問題,是物件快捷書寫方式,但是這麼好的方式,為什麼不大力推廣使用呢? 因為效能存在一些問題。 function initUI(){ with(document){ var bd=body,len=links.length; while(i < len){ update(links[i++]); } getElementById("btnInit").onclick=function(){ doSomething(); }; } } 這裡使用with語法省略了document。
with傳入的物件的屬性放入最上層,剩餘的都往下壓,導致區域性變數的訪問代價增大,所以with的效能不好。
2、catch語法
我們在使用try--catch時,當代碼執行錯誤時,會執行catch函式,catch函式中引數是錯誤物件,就是這個錯誤物件,會放到作用域鏈的頭部。 但是try--catch我們在必要的使用得使用,我們可以這樣解決。 try{ doSomething(); }catch(ex){ alert(ex.message); //作用域鏈在此處改變 } 處理後: try{ doSomething(); }catch(ex){ handleError(ex); //委託給處理器方法 } 解決方案是:將catch錯誤處理交給另外一個函式進行處理。
總結
本篇文章就到這裡了,希望能夠給你帶來幫助,也希望您能夠多多關注我們的更多內容!