this、call和apply
阿新 • • 發佈:2018-12-15
JavaScript總是指向一個物件,指向哪個物件是在執行時基於函式的執行環境動態繫結的,而非函式宣告時的環境。
this的指向
除去不常用的with和eval的情況,具體到實際應用中,this的志向大致可以分為以下4種。
- 作為物件的方法呼叫。
- 作為普通函式呼叫。
- 構造器呼叫。
- Function.prototype.call或Function.prototype.apply呼叫。
作為物件的方法呼叫
當函式作為物件的方法被呼叫時,this指向該物件:
var obj = { a:1, getA:function(){ alert(this === obj);//輸出:true alert(this.a);// 輸出:1 } }; obj.getA();
作為普通函式呼叫
當函式不作為物件的屬性被呼叫時,也就是我們常說的普通函式,此時的this總是指向全域性物件。在瀏覽器的JavaScript裡,這個全域性物件是window物件。
window.name = 'globalName'; var getName = function(){ return this.name; }; console.log(getName());// 輸出:globalName //或者 window.name = 'globalName'; var myObject = { name: 'zee', getName: function(){ return this.name; } }; var getName = myObject.getName; consolelog(getName());// globalName
構造器呼叫
JavaScript中沒有類,但是可以從構造器中建立物件,當用new操作符呼叫函式時,該函式總會返回一個物件,構造器裡的this就指向返回的這個物件
var MyClass = function(){
this.name = 'zee';
};
var obj = new MyClass();
alert(obj.name);// 輸出:zee
但用new構造器時,還要注意一個問題,如果構造器顯示地返回了一個object型別的物件,那麼此次運算結果最終會返回這個物件
var MyClass = function(){ this.name = 'zee'; return { name: anne' } }; var obj = new MyClass(); alert(obj.name); // 輸出:anne
如果構造器不顯式地返回任何資料,或者是返回一個非物件型別的資料,就不會造成上述問題:
var MyClass = function(){
this.name = 'zee';
return 'anne';// 返回string型別
};
var obj = new MyClass();
alert(obj.name); // 輸出:zee
Function.prototype.call或Function.prototype.apply呼叫
跟普通的函式呼叫相比,用Function.protoype.call或Function.prototype.apply可以動態地改變傳入函式的this
var obj1 = {
name: 'zee',
getName: function(){
return this.name;
}
};
var obj2 = {
name: 'anne'
};
console.log(obj1.getName());// 輸出:zee
console.log(obj1.getName.call(obj2));// 輸出:anne
call和apply
call和apply用途
- 改變this的指向
var obj1 = {
name: 'zee'
};
var obj2 = {
name: 'anne'
};
window.name = 'window';
var getName = function(){
alert(this.name);
};
getName();//window
getName.call(obj1);//zee
getName.call(obj2);//anne
document.getElementById('div1').onclick = function(){
var func = function(){
alert(this.id);
}
func.call(this);
}
- Function.prototype.bind 大部分高階瀏覽器都實現了內建的Function.prototype.bind,用來指定函式內部的this指向,即使沒有原生的Function.prototype.bind實現,我們可以模擬實現
Function.prototype.bind = function(context){
var self = this; //儲存原函式
return function(){// 返回一個新的函式
return self.apply(context, arguments);//執行新的函式的時候,會把之前傳入的context當作新函式體內的this
}
};
var obj = {
name: 'zee'
};
var func = function(){
alert(this.name);//輸出zee
}.bind(obj);
func();
- 借用其他物件的方法
var A = function(name){
this.name = name;
};
var B = function(){
A.apply(this, arguments);
};
B.prototype.getName = function(){
return this.name;
};
var b = new B('zee');
console.log(b.getName());//輸出:'zee'