1. 程式人生 > >js方法中var self=this的原因

js方法中var self=this的原因

每個函式在定義被ECMAScript解析器解析時,都會建立兩個特殊的變數:this和arguments,換句話說,每個函式都有屬於自己的this物件,這個this物件是在執行時基於函式的執行環境繫結的,即在全域性物件中,this指向的是window物件;在自定義函式中,this物件指向的是呼叫這個函式的物件, 也就是說,this指向的是呼叫執行環境的那個物件。 如果是在函式巢狀環境中,this指代的是呼叫外部函式或者內部函式的執行環境的物件; (注意:可以通過使用call()或者apply()改變函式執行環境的情況下,this就會指向其他物件。) 看例子吧:  /*----- 2014-2-10 這個例子是錯誤的 -----*/ function BaseType(name,age){     //用一個變數儲存當前函式執行環境中的this物件     //這裡可能會有疑問:為什麼非得把this儲存起來呢?這是因為,內部函式(比如本函式裡面包含的兩個匿名函式)     //在搜尋this變數時,只會搜尋到屬於它自己的this,而不會搜尋到包含它的那個函式的this。     //所以,為了在內部函式能使用外部函式的this物件,要給它賦值了一個名叫self的變數。

    var self=this;      this.name=name;     this.age=age;     this.sayHello=function(){         console.log("My name is "+this.name+", and i'm "+this.age+"years old.");     }     this.saySomething=function(){            //此處用法有點欠妥,完全可以不用self,而用this            //self.sayHello();            //正確的做法是:            return function () { self.sayHello(); }

           //通常用法:將上下文this快取到一個變數中            //以便在本函式作用域內包含另一個函式作用域的情況下可以繼續使用此上下文物件this            //如果省略var self=this; 這行,那麼在巢狀函式作用域內就無法訪問到本函式作用域的成員了。         

    } } var b1=new BaseType("wede",30); b1.saySomething(); //My name is wede, and i'm 30years old.  從結果來看,是預期的結果。 那麼這裡可能又會出現新的疑問:為什麼在saySomething()方法中非要用self.sayHello()來呼叫呢, 直接sayHello()多好? 其實這又涉及到另一個話題:例項成員與區域性成員。 我們建立建構函式的意義就是要用它來建立例項,那麼所有屬於例項的成員都需要用this來定義; 而只有那些不屬於例項的成員才不會用this定義; 當然,用this定義了方法以後,在函式作用域內部要呼叫此方法時,就需要加上this了。 為了證明這一點,來看下面的程式碼: function BaseType(name,age){     var self=this;     this.name=name;     this.age=age;     this.sayHello=function (){         console.log("My name is "+this.name+", and i'm "+this.age+"years old.");     }     this.saySomething=function(){         sayHello();     } } var b1=new BaseType("wede",30); b1.saySomething(); //ReferenceError: sayHello is not defined 結果顯示:sayHello方法未定義。 就是說明,我們呼叫的其實是區域性方法sayHello,而現在只有例項方法sayHello,所以會出現異常。 下面來改裝下(注意加粗的部分): function BaseType(name,age){     var self=this;     this.name=name;     this.age=age;     var sayHello=function (){         console.log("My name is "+name+", and i'm "+age+"years old.");     }     this.saySomething=function(){         sayHello();     } } var b1=new BaseType("wede",30); b1.saySomething();//My name is wede, and i'm 30years old. 可以看出,輸出了預期的結果。 而這時候,我們把sayHello方法變成了一個區域性方法(對於例項不可見),然後再在saySomething方法中呼叫就可以了。