1. 程式人生 > >關於困惑已久的var self=this的解釋

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

http ren 函數作用域 his call bird 執行環境 UNC fine

首先說下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方法中調用就可以了。

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