JS大法好,JS在手,天下我有,信JS,得永生。
這個系列的教程我一開始是寫在github上的,
但是覺得放到掘金來可以讓更多需要的人看到,
就搬到掘金專欄上啦,
如果覺得本教程對你有幫助,請點這裡去github上給我一顆Star~
教程目錄也在github上哈~
本著對技術負責的態度,任何糾正/疑問,儘管提出,我會及時修正/回答。
一定要把每個例子程式碼都拷貝到你的執行環境中邊看結果邊理解,不然學習效果減半,或者沒效果。
閒話說太多了~下面開始第一篇:
理解JS中this指向的小技巧
在看他人寫的js檔案時,會看到許多this,
對this不熟悉的人很容易蒙圈,這裡就說明如何用最簡單的方法去找this指向誰。
切記!這裡說的找“點”大法中的“.”,都是在呼叫的語句裡找,本教程的全域性物件為window!
1、找“點”大法:你找不到“.”的函式呼叫,this指向一般是window:
宣告
function foo(){
console.log(this)
}複製程式碼
呼叫
foo(); //自己去執行程式碼看this指向誰
//腦補:
window.foo(); //自己去執行程式碼看this指向誰複製程式碼
解讀
不用懷疑,也不用猶豫,找不到任何“.”,this指向window。
以後見到直接呼叫的foo,自動腦補成window.foo(),因為在這種情況下,這兩種寫法是一樣的。複製程式碼
㈠當函式/匿名函式作為引數時,你是找不到“.”的,這種情況下,函式內部的this指向window。
宣告&呼叫
function foo(callback){
callback(); //呼叫其實在這裡,你是找不到“.”的
}
foo(function(){
console.log(this); //自己去執行程式碼看this指向誰
})複製程式碼
解讀
這個例子就是,匿名函式內部列印了this,它作為引數,內部的this指向window。複製程式碼
2、找“點”大法:有“.”的函式呼叫,this指向一般是最後一個“.”左側的那個物件:
2-1、呼叫語句裡只能找到一個“.”:
宣告
var bar = {name:'我是bar'};
bar.foo = function(){
console.log(this)
};複製程式碼
呼叫
bar.foo(); //自己去執行程式碼看this指向誰複製程式碼
解讀
這個例子,我們找到了“.”的存在,“.”左側是bar,指向是bar。複製程式碼
2-2、呼叫語句裡能找到多個“.”:
宣告
var obj = {name:'我是obj'};
obj.bar = {name:'我是bar'};
obj.bar.foo = function(){
console.log(this)
};複製程式碼
呼叫
obj.bar.foo(); //自己去執行程式碼看this指向誰複製程式碼
解讀
這個例子,我們找到了倆“.”,最後一個“.”左側的物件是bar,那麼this指向就是bar。複製程式碼
㈡如果發現你找到的“.”左側是prototype,那麼再往左找一個“.”,這個“.”左側的物件是this指向。原理在不得不提的原型/原型鏈中給出。
3、物件導向中的this:
對物件導向不夠了解的同學,請儘量讀懂不得不提的原型/原型鏈
閱讀本文,就先專注於找this指向吧!
宣告
function Foo(){
this.name = 'hahaha'
console.log(this);
}
Foo.prototype.bar = function(){
console.log(this);
}
Foo.prototype.funcWithParam = function(fn){
fn();
}複製程式碼
呼叫
Foo(); //自己去執行程式碼看this指向誰
Foo.prototype.bar(); //自己去執行程式碼看this指向誰
var foo = new Foo(); //自己去執行程式碼看this指向誰
foo.name = '我是foo';
foo.bar(); //自己去執行程式碼看this指向誰
foo.funcWithParam(function(){
console.log(this); //自己去執行程式碼看this指向誰
});複製程式碼
解讀
當Foo()時,Foo被當做[普通函式],那麼遵循找“點”大法,Foo內部的this是指向window的;
當Foo.prototype.bar()時,Foo還是被當做[普通函式],遵循找“點”大法,按照2-2,發現找到了prototype,轉而遵循㈡,再向左找,發現this指向Foo;
當new Foo()時,Foo作為[建構函式]被例項化,Foo內部的this指向例項化後的Foo,也就是我宣告的foo;
當foo.bar時,遵循找“點”大法,按照2-1,發現this指向foo;
當foo.funcWithParam(匿名函式)時,匿名函式前沒有“.”,匿名函式作為引數,所以遵循㈠,發現其內部this指向window;複製程式碼
4、call和apply會改變this指向,在巧妙理解call、apply單獨詳解。
小結:
- 找不到“.”的函式呼叫,其內部的this一般指向window象;
- 找得到“.”的函式呼叫,其內部的this一般指向最後一個“.”左側的那個物件,如果左側是prototype,再向左找一個;
- 明確區分函式是[建構函式]還是[普通函式],[建構函式]內的this指向例項化後的物件;
- 函式作為引數傳遞,被呼叫時其內部的this一般指向window。
- call和apply會改變this指向,參閱巧妙理解call、apply。
- ES6/7的箭頭函式也會影響this指向,這個很簡單,我就不多講啦~
一句話來說,就是“誰調的我(普通函式),我內部的this就指向誰;new我一下(建構函式),我內部的this就指向我的例項化”
PS:
歡迎轉載,需要註明原址。
教程之間緊密聯絡,不懂的地方,請好好看下全系列教程目錄,
有沒有你不懂的那個關鍵字在裡面。
如果幫到你,別忘了給我一顆Star~