標籤:this 代碼 實踐 obj target 方式 cal get 文法
想學好javascript不是一件容易的事,而this就是其中一道坎,尤其是在用js進行物件導向開發的時候。
實際上,想要徹底搞懂this的指向確實不是一件容易的事,在《你不知道的javascript 上卷》一書中更是花了很大篇幅詳細總結了this的四種指向情景。我在艱難的啃完這本書和大量閱讀《javascript進階程式設計》、博文、以及大量實踐中終於是弄懂了this。確實是,有些知識是需要反覆驗證、理解、總結,直至豁然開朗,構建成屬於自己的理論體系。
那麼進入本文:
javascript中的this一般可以分為四種情況:
- 函數調用;
- 方法調用;
- 構造器調用;
- 間接調用。
1.函數調用
在非strict 模式下,函數調用時,函數內部的this會預設指向window。
function fn(){
console.log(this);
}
fn();//函數調用 this --> window
2.方法調用
方法調用就是,一個函數被定義為一個對象的屬性(方法),並且以[對象].[方法]()的形式被調用,函數內部的this指向[對象]本身。
例如:
var obj={ fn:function(){
console.log(this);
}}
obj.fn();//方法調用 this --> obj
有些情況下,可能會將函數調用誤認為是方法調用。
例如:
var obj={ fn:function(){
console.log(this);
}};
function foo(callback){ callback();}foo(obj.fn);//點擊觸發時,列印:window
可能會有人對上面代碼的結果產生困惑,實際上作為回呼函數的函數屬於函數調用。obj.fn並不是方法調用,而是儲存了一個函數的地址,並成為了一個實參。
3.構造器調用
所謂構造器調用,就是當函數與new關鍵字配合建立執行個體時,函數內部的this在會指向新建立的執行個體。
例如:
function Person(name){ this.name=name;}
var p=new Person(‘Bob‘);//構造器調用 函數執行時this --> p
console.log(p.name);//‘Bob‘
4.間接調用
這種函數調用方式需要藉助兩個方法:call()或者apply()。
文法:[函數].call(obj,arg1,arg2,...)或者[函數].apply(obj,[arguments])
通過一個函數來調用call()或者apply()時,函數中的this被明確的規定指向第一個參數obj,這種方式常常用於對其他對象方法的借用。
例如:
var obj1={ name:‘小明‘,
say:function(){
console.log(this.name);
}
};
var obj2={
name:‘小紅‘
};
obj1.say();//方法調用 this --> obj1 列印結果:小明
obj1.say.call(obj2);//間接調用 this --> obj2 列印結果:小紅
其次,還有一個方法bind()也可以將函數的this強制指向某一個對象。
文法:[函數].bind(obj)
傳回值:函數的副本,該副本中的this將永遠指向obj
bind()方法與call()、apply()的區別就是:bind()不會立即執行函數,而是返回一個函數的副本。
具體的作用請戳 強大的bind方法
其實還有一種很特殊的情況:
函數作為事件的回呼函數,函數內部的this指向事件綁定的對象。
javascript中this的指向問題