前端三部曲:詳解JavaScript中this的指向
很多初學JavaScript的同學,都找不準函式或者方法中的this到底指向誰,其實並沒有那麼複雜,只需要記住一個口訣就能正確找到this的指向:不管函式或者方法是如何宣告的,要看這個函式或者方法最終是誰呼叫的,誰最終呼叫這個函式或方法,那麼這個函式或方法中的this就是誰.下面從函式呼叫方式著手詳細給大家介紹一下這個口訣.
-
作為普通函式中的this
示例程式碼function welcome( ) {
console.log(“黑馬程式設計師深圳中心前端與移動開發學科歡迎大家!”);
console.log(this);
}
welcome(); //第5行
window.welcome();//第6行
大家都知道寫一個全域性函式相當於給window物件新增了一個方法,所以第5行呼叫welcome函式和第6行呼叫welcome函式本質是一樣的,所以welcome函式最終是window物件在呼叫,所以welcome函式內部的this就指向了window物件.執行結果如下.
-
作為物件的方法中的this
示例程式碼var name = “黑馬程式設計師”;
var obj = {
name: “傳智播客”,
sayHi: function () {
console.log(“深圳就在這裡,黑馬對你不離不棄!”);
console.log(this);
}
};
obj.sayHi();
最後1行的sayHi方法是由obj物件點出來呼叫的,所以sayHi方法中的this指向obj物件.所以輸出的是obj物件中的name的值, 結果如下:
3. 綜合案例
3.1 案例一
function welcome( ) {
console.log("黑馬程式設計師深圳中心前端與移動開發學科歡迎大家!");
console.log(this);
}
var name = "黑馬程式設計師";
var obj = {
name: "傳智播客",
sayHi: function () {
console.log("深圳就在這裡,黑馬對你不離不棄!"); //第10行
console.log(this);//第11行
}
};
welcome = obj.sayHi; //第15行
welcome(); //第16行 這個時候,這個welcome函式中的this指向誰呢?
這裡要搞明白的是第15行程式碼的含義, 這句話的作用是把obj物件裡面的sayHi函式的函式體賦值給welcome, 所以在第16行呼叫welcome函式的時候,執行的程式碼其實是obj中sayHi的函式體. 那麼執行的就是第10、11行, 那麼這個this是誰呢? 其實很簡單,不要看這個方法是宣告在obj物件裡面的, 要看這個方法是在第16行呼叫,是window呼叫的,所以此時這個this是window,輸出的結果就是window的name屬性,就是那個全域性name的值, 結果如下:
3.2 案例二
function welcome( ) {
console.log("黑馬程式設計師深圳中心前端與移動開發學科歡迎大家!"); //第2行
console.log(this); //第3行
}
var name = "黑馬程式設計師";
var obj = {
name: "傳智播客",
sayHi: function () {
console.log("深圳就在這裡,黑馬對你不離不棄!"); //第10行
console.log(this);//第11行
}
};
//變化在這裡.....
obj.sayHi = welcome; //第15行
obj.sayHi(); //第16行 這個時候,obj.sayH函式中的this指向誰呢?
這裡同樣要搞明白第15行程式碼的含義,這句話的意思是把welcome的函式體賦值給obj物件的sayHi函式, 所以在第16行呼叫obj物件的sayHi函式實際上執行的程式碼是第2行第3行, 那第3行的this是誰呢? 此時不要看這個welcome是怎麼宣告的, 要看這個程式碼是在第16行呼叫的,是obj物件點出來呼叫的,所以this指向obj.結果如下:
3.3 案例三
var name = "黑馬程式設計師";
var p1 = {
name: "深圳中心",
dog: {
name: "旺財",
sayHi: function(){
console.log(this);
}
}
}
p1.dog.sayHi();
最後一行這裡給人的錯覺好像sayHi方法是p1點出來呼叫的,事實這種想法是錯誤的,p1點出來的只是dog物件, sayHi方法還是由dog點出來呼叫的,所以sayHi方法中的this還是指向dog物件.所以輸出的結果如下:
-
建構函式中的this
4.1 直接呼叫建構函式function Student(name, age){
this.name = name; //第2行
this.age = age;//第3行
}var s1 = Student(“黑馬”,12); //第6行
console.log(s1);
console.log(window.name);
console.log(window.age);
大家注意看第6行,呼叫Student函式的時候沒有用new關鍵字,那麼這就意味著Student函式是window點出來呼叫的,所以Student函式中的this就是window,那麼第2行第3行就是在給window新增name和age屬性,值分別是黑馬和12. 然後函式內部沒有寫return關鍵字那預設返回值是undefined.所以s1接受到的是undefined. 整個輸出結果如下:
4.2 使用new呼叫建構函式
function Student(name, age){
this.name = name; //第2行
this.age = age;//第3行
}
var s1 = new Student("黑馬",12); //第6行
console.log(s1); //第7行
大家都知道new關鍵字會建立一個物件,並且會把建構函式中的this指向這個物件,並且還會把這個物件自動返回, 那麼執行完第6行程式碼, s1就是那個new關鍵字建立並返回的物件.在第2行第3行也已經給這個物件新增了name和age屬性. 所以上面的程式碼執行結果如下:
4.2 為建構函式手動return後的情況
這裡再來看看如果給建構函式新增了return關鍵字會如何,程式碼如下:
function Student(name, age) {
this.name = name; //第2行
this.age = age;//第3行
console.log(this);
return [10, 20, 30];
}
var s1 = new Student("黑馬", 12); //第8行
console.log(s1); //第9行
說到這裡大家就要注意,因為new關鍵字會自動幫我們返回他建立的物件,所以一般在建構函式中是不用寫return返回值的, 那萬一建構函式中就是寫了return返回值會怎麼樣呢?
這個時候就要看return關鍵字後面返回的值是什麼型別的,如果返回的是數值型別/字串型別/布林型別/null/undefined,那麼會忽略這個返回值. 如果返回的值不是這些型別的,比如是一個陣列或者一個物件,那麼這個返回值會覆蓋原來new關鍵字自動返回的那個物件. 所以上面程式碼執行的結果如下:
但是建構函式中的this還是new關鍵字建立的那個物件(驗證看第10行輸出的結果), 只是這個物件返回的時候被return關鍵字返回的陣列給覆蓋了,所以s1接受不到而已.
5. 修改函式中this的預設指向
以上我們討論的是,預設情況下,函式中this的指向。實際上JavaScript提供了一套機制,允許我們對函式中的this指向進行修改,可以讓函式中的this指向我們想要讓他指向的物件。
var obj = {
name: "張三"
};
function welcome() {
console.log(this);
}
welcome();
大家現在都知道上述程式碼中welcome函式中this指向window物件, 輸出的是window, 但是我們現在想讓welcome函式中的this指向obj物件,那應該怎麼做呢?
肯定是不能直接修改函式中this的指向的,直接修改會報錯, 因為this被JavaScript設計為只讀,程式碼如下:
var obj = {
name: "張三"
};
function welcome() {
this = obj; //這句程式碼在執行的時候,會報錯,無法執行
console.log(this);
}
welcome();
這個時候,要實現這個效果,要想讓welcome函式中的this指向obj, 就要使用函式上下文呼叫模式,比如call、 apply、 bind。
var obj = {
name: "張三"
};
function welcome() {
console.log(this);
}
welcome.call(obj); //使用函式上下文呼叫模式,想要讓welcome中的this指向誰,就把誰傳入.
這個時候,welcome函式被呼叫,但是welcome函式內部的this就指向obj物件了。
關於函式上下文的呼叫模式,具體內容,我們將在後續章節繼續為大家介紹,歡迎大家訂閱關注。
相關文章
- JavaScript 的 this 指向和繫結詳解JavaScript
- JavaScript 中 This 的指向JavaScript
- JavaScript中this指向以及改變this指向JavaScript
- JavaScript中this指向的總結JavaScript
- JavaScript中的this詳解JavaScript
- JavaScript中this指向問題JavaScript
- 全面解析JavaScript中this指向JavaScript
- JavaScript的this的指向JavaScript
- 【JavaScript】聊聊js中關於this的指向JavaScriptJS
- JavaScript 內的 this 指向JavaScript
- JavaScript內的this指向JavaScript
- javascript:this指向JavaScript
- JavaScript 你真的瞭解this指向嗎JavaScript
- JavaScript中的async/await詳解JavaScriptAI
- 合格前端系列第六彈-從指向看JavaScript前端JavaScript
- javascript的this指向問題JavaScript
- 箭頭函式this指向詳解函式
- JavaScript_this指向JavaScript
- 【JavaScript】徹底明白this在函式中的指向JavaScript函式
- javascript中的閉包closure詳解JavaScript
- JavaScript中 Map 物件詳解JavaScript物件
- JS中的this指向問題(詳細版plus)JS
- JavaScript中的包裝型別詳解JavaScript型別
- 關於javascript的this指向問題JavaScript
- 前端-JavaScript中的class前端JavaScript
- 容易被遺忘的前端基礎:JavaScript 記憶體詳解前端JavaScript記憶體
- JavaScript this詳解JavaScript
- js中的this指向JS
- 詳細資訊用於javascript中的承諾使用詳解JavaScript
- 詳解JavaScript中的嵌入式資料庫JavaScript資料庫
- 6. JavaScript this指向相關JavaScript
- 前端進階課程之this指向前端
- JS中this指向的更改JS
- 閉包詳解二:JavaScript中的高階函式JavaScript函式
- 詳解JavaScript原型JavaScript原型
- JavaScript之this詳解JavaScript
- JavaScript事件詳解JavaScript事件
- JavaScript Promise 詳解JavaScriptPromise