1. 程式人生 > 程式設計 >javascript作用域和作用域鏈詳解

javascript作用域和作用域鏈詳解

目錄
  • 一、的作用域
    • 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錯誤處理交給另外一個函式進行處理。
        

        總結

        本篇文章就到這裡了,希望能夠給你帶來幫助,也希望您能夠多多關注我們的更多內容!