this指向问题是个老问题了,网上的教程很多都是相互copy的,让萌新一脸蒙,这里简单总结下,保证一次性搞懂。
首先,这里有个问题是js分严格模式和非严格模式,严格模式和非严格模式下this指向稍微有点区别,主要就是全局作用域中普通函数中的this指向问题,严格模式下是指向undefined的,非严格模式下是指向window。
现在一般用的都是严格模式,比如vue中就是这样。
本文案例都是在严格模式下。
话入正题:箭头函数和普通函数有什么区别?
箭头函数没有arguments参数、无法作为构造函数,不能被new、this取决于上下文,本身没有this、使用call,apply等无法改变this指向。
而上面箭头函数不能做的普通函数都可以,其中普通函数的this指向调用方。
普通函数this指向?
答:普通函数的this指向调用方。
eg1:
首先这两种写法都是一样的,这里a.say
是对象a
在调用,因为普通函数的this指向调用方,因此这里的this
指向a
。
eg2:我们再来验证下:
这里我们将a.say
的方法引用赋值给了b
,然后用window.b
调用,因此这里的this.name
中this
指向window
箭头函数this指向?
答:箭头函数本身没有this,this取决于定义时的上下文。也就是说箭头函数中的this指向的是定义时的this,而不是执行时候的this。
eg1:
这里say
方法是箭头函数,在定义时a
对象内是没有this的,当前this
指向window
.。window.b()
虽然最后打印的是全局name
,但是实际上是和调用方无关的,this
是在定义的时候就确定了。
eg2:
这里箭头函数定义在函数内部,若当做普通函数直接调用,this
为undefined
,若当做构造函数实例化则this
指向构造函数所创建的对象实例。
有的同学就想,哎呀?不是一开始就确定了this吗,怎么值还不一样诶?注意,这里当做构造函数使用相当于把它当做类了,性质都不一样,this不一样完全是可以理解的。还有一点要注意,这里是用的new 一个实例的方式调用的,在严格模式下构造函数不加new直接调用,因为
this
是undefined
,this.name = xxxx 会报错,如下:
eg3:
这个例子出自这篇文章,具有误导性,但是理解了上面eg2这个例子你就明白了。这里person
当做构造函数在使用,函数内getval
是定义在构造函数内部的箭头函数,因为对象o在定义时是没有this的,因此getval
内的this
是构造函数的this
,也就是指向构造函数所创建的对象实例。但是,person
并没有返回这个this
,该构造函数返回的是另一个对象o
,但无论是返回的什么,getval
的this
在定义时就确定了,那就是构造函数内的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 = '这是函数内定义的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内部'
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();
若对你有帮助,请点个赞吧,谢谢支持!
本文地址:https://www.jianshu.com/p/cdf9e4f6312b,转载请注明出处,谢谢。
参考:
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