“寫在前面:js中的this指向是在調(diào)用過程中確定的肮帐,而不是定義過程中”
5種情況,如下:
- 普通函數(shù)調(diào)用
// 例1
function b () {
console.log(this) // window
}
b()
// 例2
var id = 1
function a () {
console.log(this.id) // 1
}
a()
答:該情況下,this指向全局對象window。例2中id定義在全局對象上雷客,實際為window.id,因此打出來的1桥狡。
- 對象調(diào)用
// 例1
let obj = {
id:1,
test1() {
console.log(this.id) // 1
}
}
obj.test1()
// 例2
test2() {
console.log(this.id)
}
let obj2 = {}
obj2.id = 2
obj2.do = test2
obj2.do() // 2
答:例1中obj調(diào)用了test1方法搅裙,那么該this就指向該對象皱卓。例2中,當(dāng)定義test2方法時部逮,并不能確定該this的指向娜汁,只有當(dāng)該方法被放入obj2中,并且obj2調(diào)用它時兄朋,此時我們才能確定該this指向obj2掐禁。(記住文章開頭寫在前面的那句話)
- 構(gòu)造函數(shù)
function A(id) {
this.id = id
}
let a = new A(1)
a.id = 1
let b = new A(2)
b.id = 2
答:在構(gòu)造函數(shù)中的this代表的是調(diào)用該構(gòu)造函數(shù)的那個對象,說白了就是“誰調(diào)用颅和,就指向誰”穆桂。例1中this指向a,例2中this指向b融虽。
new 關(guān)鍵字可以改變this指向。
- apply/call可以改變this指向
let obj = {
id: 1,
test() {
console.log(this.id)
}
}
let obj1 = {
id: 2
}
obj.test.apply(obj1) // 2
答:在obj.test()中的this是指向obj的灼芭,這是沒問題的有额。通過apply我們可以強制更改this指向obj1,因此輸出的結(jié)果為2彼绷。
apply/call的用法可以參考我的這篇講解
5.箭頭函數(shù)
// 例1
let obj = {
id: 1,
a() {
setTimeout( () => {
console.log(this.id) // 1
})
}
}
obj.a()
// 例2
let obj2 = {
id: 2,
a: () => {
console.log(this) // window
}
}
obj2.a()
答:箭頭函數(shù)中的this指向巍佑,與上層作用域鏈保持一致,說白了就是“上層this指向誰寄悯,他就指向誰”萤衰。例1中,setTimeout中的this指向與a()方法一致猜旬,a方法則指向obj脆栋,因此輸出1。例2中洒擦,方法a為箭頭函數(shù)椿争,this指向與上層一致,則指向window熟嫩。
大家對于例2可能有點疑惑秦踪,為什么會指向window,而不是obj掸茅,是不是與之前的“誰調(diào)用就指向誰”相矛盾椅邓,1.大家對于箭頭函數(shù)需要單獨看待哦~,不能和普通函數(shù)一致處理昧狮。
2.方法a的上層作用域就是window景馁,obj2只是一個對象,并不是一個作用域鏈(可以去細(xì)了解下作用域鏈方面的知識)陵且,最簡單的作用域鏈就是一個方法裁僧,方法內(nèi)/方法外是不同的作用域个束。
舉個例子:
function a() {
var id = 1
}
console.log(id) // undefined
從這大家可以看出,在a方法內(nèi)定義的方法聊疲,在外部是訪問不到的茬底。這是因為方法a內(nèi)部是一個局部作用域,而在外部是一個全局作用域获洲,全局作用域中是訪問不到局部作用域的阱表。