this和執行內容實現代碼

來源:互聯網
上載者:User

函數的執行內容由當前的運行環境而定:
1. 全域變數和全域函數附屬於全域對象(window),因此使用”var”或”this”兩種方法定義全域變數是等效的。
2. 執行內容和範圍不同。執行內容在運行時確定,隨時可能改變,而範圍則在定義時確定,永遠不會變。
3. 如果當前執行的是一個對象的方法,則執行內容就是這個方法所附屬的對象。
4. 如果當前是一個建立對象的過程或者執行一個對象的方法,則執行內容就是這個正在被建立的對象。
5. 如果一個方法在執行時沒有明確指定附屬對象,則這個方法的上下文為全域對象。
6. 使用call和apply可以改變對象的執行內容。
看下面的例子: 複製代碼 代碼如下:var v1 = "global variable"; //全域變數附屬於對象
//this.v1 = "global variable with this"; //全域變數定義時使用var v1和this.v1兩種方法等效。
function func1(){
var v1 = "part variable";
writeHtml(v1);
writeHtml(this.v1);
}
func1(); //part variable
//global variable

因為func1中有和全域對象同名的v1變數,所以在func1中直接引用v1引用的是func1中定義的變數。javascript同樣有局部變數隱藏全域變數的特性。但func1沒有明確的指定附屬對象,因此他的執行內容是全域對象,使用this引用變數的是全域變數。
再看一個稍微複雜一點的例子: 複製代碼 代碼如下:function ftest(){
var v = "v1v1v1";
this.this_v = "this_v";
return function(){
writeHtml(v);
writeHtml(this.this_v);
}
}
var a = ftest();
var v = "v2v2v2";
writeHtml(this_v); // this_v
a(); //v1v1v1
//this_v

當ftest當做函數來執行時,上下文為全域對象。所以在ftest中使用this定義的變數成為了全域變數。所以我們在ftest外面直接使用變數名訪問this_v的值。但是,由於ftest中返回的匿名函數是定義在ftest內部的,所以這個匿名函數的範圍就是在ftest內部。因此當有全域變數v和局部變數v同名時,這個匿名函數訪問到的是ftest內部定義的變數v。
接下來把ftest當做類,使用new關鍵字來執行個體化: 複製代碼 代碼如下:function ftest(){
var v = "v1v1v1";
this.this_v = "this_v";
return function(){
writeHtml(v);
writeHtml(this.this_v);
}
}
var a = new ftest();
var v = "v2v2v2";
//writeHtml(this_v); // 錯誤:this_v未定義
a(); //v1v1v1
//undefined

把ftest當做對象來執行個體化時,在對象的建立過程中,上下文為被建立的對象本身。注意,這個時候建立的對象是ftest的執行個體,而建立完成以後又返回了一個函數,這導致了new ftest()執行個體化後返回的是一個函數,而不是ftest()執行個體化後對象的引用。因此,這個已經執行個體化的對象無法被引用。當我們定義這個被返回的函數時,因為沒有用this指定這個函數的上下文,因此這個被返回的函數上下文為全域對象,範圍為ftest()函數內部。所以函數a()執行時的由於上下文中沒有定義this_v變數,導致了訪問錯誤。
注意,上面的代碼: 複製代碼 代碼如下:function ftest(){
return function(){
}
}

這樣的形式並不是一個靜態封裝環境,靜態封裝環境應該是:在一個函數定義完成後立即執行,並且執行完成後返回函數中的某一個內建函式。
我們看下面一個例子,觀察範圍和上下文對變數引用的影響。 複製代碼 代碼如下:var v = "global variable";
function method(){
writeHtml(v);
writeHtml(this.v);
}
var Class1 = function(){
var v = "private variable";
this.v = "object variable";

var method2 = method;
this.method2 = method;

var method3 = function(){
writeHtml(v);
writeHtml(this.v);
}
this.method3 = function(){
writeHtml(v);
writeHtml(this.v);
}

method2(); //global variable
//global variable
this.method2(); //global variable
//object variable
method3(); //private variable
//global variable
this.method3();//private variable
//object variable
}
var obj = new Class1();

由於method在全域中定義,所以method的範圍在定義的時候就被確定為全域的。所以method2在Class1內部被調用時,其範圍與是全域,上下文是全域對象。因此,在函數中訪問到的變數都是全域變數。
同理,this.method2在被調用時,其範圍是全域,但是由於該函數在定義時使用this關鍵字指明了其上下文為Class1的對象,所以在該函數訪問沒有上下文限定的變數時訪問到的是全域變數,訪問有上下文限定的變數時為訪問到的是當前上下文中對應的變數。
在調用method3和this.method3時,在訪問沒有上下文限定的變數時訪問到的是局部變數,因為局部變數隱藏了全域變數。有上下文限定時和method2相同,訪問到的是當前上下問文中的變數。
使用call和apply可以改變執行內容,由於call和apply只是參數類型不一樣,因此例子下面都用call來示範。 複製代碼 代碼如下:var v = "global variable";
var method = function(){
writeHtml(this.v);
}
var Class2 = function(){
this.v = "object variable in instance of Class2";
this.method = function(){
writeHtml(this.v);
}
}
var Class3 = function(){
this.v = "object variable in instance of Class3";
this.method = function(){
writeHtml(this.v);
}
}

var obj2 = new Class2();
var obj3 = new Class3();

method(); //global variable
obj2.method(); //object variable in instance of Class2
obj3.method(); //object variable in instance of Class3

method.call(obj2); //object variable in instance of Class2
method.call(obj3); //object variable in instance of Class3
obj2.method.call(obj3); //object variable in instance of Class3
obj2.method.call(this); //global variable
obj3.method.call(obj2); //object variable in instance of Class2
obj3.method.call(this); //global variable

可以看到,使用call或apply可以將方法綁定到指定的上下文中。在全域環境中this指向的上下文為全域對象。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.