外观
this 指向怎么判断?
普通函数的 this 由调用方式决定,不由它写在哪决定。箭头函数没有自己的 this,用的是定义时外层函数的 this。
按这个顺序判断:
new调用:this是新对象。call/apply/bind:this是传入的对象。new的优先级比bind高。- 方法调用
obj.fn():this是obj。 - 直接调用
fn():严格模式是undefined,否则是全局对象。 - 箭头函数不走上面的规则。
原理
js
"use strict"
const obj = {
name: "obj",
regular() {
return this.name
},
arrow: () => {
return this
}
}
obj.regular() // "obj"
const fn = obj.regular
fn() // 严格模式下 this 是 undefined,读 name 会抛错把方法拆出来交给 setTimeout 或事件监听后,调用方不再是原对象,this 就变了。要保住它,可以用箭头函数包一层,或事先 bind。类字段箭头函数也能保住 this,但每个实例都会有一份函数,不在原型上共享。
嵌套的普通函数不会继承外层 this。同一位置写成箭头函数才会。
追问
箭头函数能当构造函数吗?
不能。它没有 [[Construct]],也没有自己的 prototype,new 会抛错。
类字段箭头函数和原型方法怎么选?
回调要传给别人、又必须指向实例时,类字段箭头函数省事。希望子类共享、或要放在原型上覆盖,用原型方法,在传出去的地方再绑定。
bind 之后还能 new 吗?
可以。new 时忽略 bind 固定的 this,预先传入的参数仍然生效。见 手写 bind。
易错点
obj.fn()和const f = obj.fn; f()的this不同。- DOM 监听里,普通函数的
this是当前元素;箭头函数的this是定义位置的外层,通常不是元素。 - 严格模式不会把独立调用的
this修成全局对象。