this指向問題是個老問題了审洞,網(wǎng)上的教程很多都是相互copy的呼畸,讓萌新一臉蒙痕支,這里簡單總結(jié)下,保證一次性搞懂蛮原。
首先卧须,這里有個問題是js分嚴格模式和非嚴格模式,嚴格模式和非嚴格模式下this指向稍微有點區(qū)別儒陨,主要就是全局作用域中普通函數(shù)中的this指向問題花嘶,嚴格模式下是指向undefined的,非嚴格模式下是指向window蹦漠。
現(xiàn)在一般用的都是嚴格模式椭员,比如vue中就是這樣。
本文案例都是在嚴格模式下津辩。
話入正題:箭頭函數(shù)和普通函數(shù)有什么區(qū)別拆撼?
箭頭函數(shù)沒有arguments參數(shù)容劳、無法作為構(gòu)造函數(shù)喘沿,不能被new、this取決于上下文竭贩,本身沒有this蚜印、使用call,apply等無法改變this指向留量。
而上面箭頭函數(shù)不能做的普通函數(shù)都可以窄赋,其中普通函數(shù)的this指向調(diào)用方哟冬。
普通函數(shù)this指向?
答:普通函數(shù)的this指向調(diào)用方忆绰。
eg1:
首先這兩種寫法都是一樣的浩峡,這里a.say
是對象a
在調(diào)用,因為普通函數(shù)的this指向調(diào)用方错敢,因此這里的this
指向a
翰灾。
eg2:我們再來驗證下:
這里我們將a.say
的方法引用賦值給了b
,然后用window.b
調(diào)用稚茅,因此這里的this.name
中this
指向window
箭頭函數(shù)this指向纸淮?
答:箭頭函數(shù)本身沒有this,this取決于定義時的上下文亚享。也就是說箭頭函數(shù)中的this指向的是定義時的this咽块,而不是執(zhí)行時候的this。
eg1:
這里say
方法是箭頭函數(shù)欺税,在定義時a
對象內(nèi)是沒有this的侈沪,當(dāng)前this
指向window
.。window.b()
雖然最后打印的是全局name
晚凿,但是實際上是和調(diào)用方無關(guān)的峭竣,this
是在定義的時候就確定了。
eg2:
這里箭頭函數(shù)定義在函數(shù)內(nèi)部晃虫,若當(dāng)做普通函數(shù)直接調(diào)用皆撩,this
為undefined
,若當(dāng)做構(gòu)造函數(shù)實例化則this
指向構(gòu)造函數(shù)所創(chuàng)建的對象實例哲银。
有的同學(xué)就想扛吞,哎呀?不是一開始就確定了this嗎荆责,怎么值還不一樣誒滥比?注意,這里當(dāng)做構(gòu)造函數(shù)使用相當(dāng)于把它當(dāng)做類了做院,性質(zhì)都不一樣盲泛,this不一樣完全是可以理解的。還有一點要注意键耕,這里是用的new 一個實例的方式調(diào)用的寺滚,在嚴格模式下構(gòu)造函數(shù)不加new直接調(diào)用,因為
this
是undefined
屈雄,this.name = xxxx 會報錯村视,如下:
eg3:
這個例子出自這篇文章,具有誤導(dǎo)性酒奶,但是理解了上面eg2這個例子你就明白了蚁孔。這里person
當(dāng)做構(gòu)造函數(shù)在使用奶赔,函數(shù)內(nèi)getval
是定義在構(gòu)造函數(shù)內(nèi)部的箭頭函數(shù),因為對象o在定義時是沒有this的杠氢,因此getval
內(nèi)的this
是構(gòu)造函數(shù)的this
站刑,也就是指向構(gòu)造函數(shù)所創(chuàng)建的對象實例。但是鼻百,person
并沒有返回這個this
笛钝,該構(gòu)造函數(shù)返回的是另一個對象o
,但無論是返回的什么愕宋,getval
的this
在定義時就確定了玻靡,那就是構(gòu)造函數(shù)內(nèi)的this
。
下面是測試使用的代碼中贝,方便大家測試:
// ----------------- 分割線 ---------------------
"use strict"
window.name = '這是全局定義的name'
var a = {
name: '11',
say(){
console.log(this.name)
}
}
a.say()
// ----------------- 分割線 ---------------------
"use strict"
window.name = '這是全局定義的name'
var a = {
name: '11',
say(){
console.log(this.name)
}
}
var b = a.say
window.b()
// ----------------- 分割線 ---------------------
"use strict"
window.name = '這是全局定義的name'
var a = {
name: '11',
say: () => {
console.log(this.name)
}
}
a.say()
var b = a.say
window.b()
// ----------------- 分割線 ---------------------
"use strict"
var fn = function () {
this.name = '這是函數(shù)內(nèi)定義的name'
console.log(this)
var a = {
name: '11',
say: () => {
console.log(this)
}
}
a.say()
}
var b = new fn()
// fn()
// ----------------- 分割線 ---------------------
"use strict"
function person(fg) {
this.name = '這是person內(nèi)部'
let o = new Object()
o.flag = fg
o.getval = () => {
console.log(this)
}
return o
}
let pp = new person('251')
pp.getval()
進階:注意this指向改變問題
"use strict"
var obj = {
func() {
console.log('-----', this)
function fn() {
console.log('func', this)
}
fn()
},
func1() {
console.log('-----', this)
setTimeout(function () {
console.log('func1', this);
})
},
func2() {
console.log('-----', this)
setTimeout(() => {
console.log('func2', this);
})
}
}
obj.func();
obj.func1();
obj.func2();
若對你有幫助囤捻,請點個贊吧,謝謝支持邻寿!
本文地址:http://www.reibang.com/p/cdf9e4f6312b蝎土,轉(zhuǎn)載請注明出處,謝謝绣否。
參考:
https://blog.csdn.net/m0_61843874/article/details/123247934
https://blog.csdn.net/tanzhou123/article/details/105919159?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165577960616782388095394%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=165577960616782388095394&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allbaidu_landing_v2~default-1-105919159-null-null.142v19control,157v15new_3&utm_term=%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B0%E7%9A%84this%E6%8C%87%E5%90%91+%E9%98%AE%E4%B8%80%E5%B3%B0&spm=1018.2226.3001.4187