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方法中調用就可以了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章