關於困惑已久的var self=this的解釋


首先說下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(); }
           //詳見:http://skybirdzw.blog.163.com/blog/static/72570626201411032516719/ 

    }
}
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方法中調用就可以了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM