this到底是什麼?
阿新 • • 發佈:2020-06-29
前言
this是JavaScript世界最讓人迷惑的關鍵字之一,如果不明白this的本質,基本上會被一線網際網路公司的面試官扣大量的分。上下文問有提到過this是上下文中確定的那麼我們來了解下什麼是this。
為什麼要有this?
function func() {
console.log(aaa);
}
複製程式碼
如上述程式碼,函式func列印變數aaa,問題是這個函式func可以在任意其他執行上下文中被呼叫,因此這個a可能就指向不同了。
this就是指向當前程式碼執行時所處的上下文環境
this的一些理解
this 既不指向函式自身也不指向函式的作用域
- this的指向,是在函式被呼叫的時候確定的,也就是執行上下文被建立時確定的。
- this 的指向和函式宣告的位置沒有任何關係,只取決於函式的呼叫位置(也即由誰、在什麼地方呼叫這個函式) 。
- 正因為在執行上下文的建立階段this的指向就已經被確定了,在執行階段this指向不可再被更改。
this指向規則
預設指向
預設this是指向全域性物件window的
function func() {
console.log( this.b ); // this指向全域性物件
}
var b = 3;
func(); // 3
複製程式碼
- 這是在預設正常執行環境下會執行window
- 如果開啟了嚴格模式,那麼func()將會變為undefined,this執行undefiend
function func() {
"use strict";//函式體處於嚴格模式下,this指向undefined
console.log(this.age);
}
var age = "22";
(function() {
func(); //age of undefined
})();
複製程式碼
setTimeout和setInterval指向?
可以發現在setInterval和setTimeout中傳入函式時,函式中的this會指向window物件
var num = 0;
class Obj {
constructor(num){
this.num = num;
}
func(){
console .log(this.num);
}
func1(){
setTimeout(function () {
console.log("setTimeout:"+this.num);
},1000)
}
func2(){
setInterval(function () {
console.log(this.num);
},2000)
}
}
var obj = new Obj(1);
obj.func();//>> 1  輸出的是obj.num
obj.func1()//>> setTimeout:0  輸出的是window.num
obj.func2()//>> 0 0 0 0 ……  輸出的是window.num
複製程式碼
可能是匿名函式做的鬼>v<,當然可以使用bind進行修正this指向即可解決
隱式this
通過執行時的上下文來決定,也就是呼叫的位置。
function func() {
console.log(this.a);
}
var obj = {
a: 2,func: func
};
obj.func(); // 2
複製程式碼
- 找到呼叫位置,由 obj 物件來呼叫函式func,
- 此時可以說函式func被呼叫時,obj 物件“擁有”或者“包含”func函式,
- 所以此時的 this 指向呼叫 func 函式的 obj 物件。
隱式丟失?
function func() {
console.log( this.a );
}
var obj = {
a: "coffe1891",func: func
};
var bar = obj.func; // 間接引用,見本文【壹.2.3.6】。此時bar和obj.func其實
// 都指向記憶體中的函式func本身。
var a = "oops,global"; // a 是全域性物件window的屬性,也是全域性變數
bar(); //>> oops,global
複製程式碼
- 可以理解為 bar 是 obj.func 的一個引用,但是實際上,它引用的是func函式本身
- bar() 其實是一個不帶任何定語的獨立函式呼叫,所以就按預設指向,執行window
顯式this
JavaScript內建物件Function的三個原型方法call()、apply()和bind(),它們的第一個引數是一個物件,它們會把這個物件繫結到this,接著在呼叫函式時讓this指向這個物件。
var a = "makai";
function func() {
console.log( this.a );
}
var obj = {
a:"123123"
};
func.call(obj); // 123123
// 在呼叫 func 時強制把它的 this 繫結到 obj 上
複製程式碼
bind和call就不用我多說了把 bind不會立即執行,而apply會立即執行和call一樣,區別在於傳參不同
new中的this
通過 new的方式,this永遠指向新建立的物件
function func(name) {
this.name = name;
this.getName = function() {
return this.name;
};
}
var obj = new func("biubiubiu"); //this會指向obj
obj.getName()//biubiubiu
複製程式碼
箭頭函式的this
箭頭函式的自身是沒有this的,箭頭函式的 this與宣告所在的上下文相同,預設為window,嚴格模式為undefined
var b = 11
var obj = {
b: 22,a: () => {
console.log(this.b);
}
}
// 物件呼叫箭頭函式
obj.a(); // 11 thi=>window
複製程式碼
over 快樂每一天