013.This 带来的困惑.md
-
初学者 this 容易混淆,React 也要使用 bind 绑定 this, this 不利于测试,使用纯函数的话可以根据函数作用域对入参出参做测试,不需要预先初始化环境。
-
Object.assign()做 一层浅拷贝可避免使用 this
-
class 带来的困惑主要是在 constructor 中的 this 或者在 super()中的 this 的问题,主要因为成员函数挂到 prototype。
-
prototype 中的对象依赖 this,this 丢了就访问不到原型链,对于尽量不使用 this,可以在对象模型中设置 setter/getter,通过传参出参的方式进行访问。
function getPerson(initalName) {
let name = initlName;
const person = {
setName(strName) {
name = strName
}
}
return person
}
- 生成的 person 对象不但是个简单 Object,由于没有调用 this,不存在 this 丢失的情况。
-
默认绑定,区分严格模式和非严格模式,严格模式下 this 为 undefined
-
隐式绑定: 函数被对象引用起来调用, this 会绑定在引用对象上
-
别名丢失隐式绑定: 调用函数引用时,this 根据调用环境(执行上下文)
function foo() {
console.log(this.count)
}
var count = 1
var obj = {
count: 2,
foo: foo
}
var bar = obj.foo // 函数别名
bar() // 1 根据执行上下文决定, 这里应该是全局上下文而不是函数执行上下文
- 回调丢失隐式绑定: 回调函数执行调用到 this,会使用回调函数里面的 this
- bind 显示绑定
function foo() {
console.log(this.count)
}
var obj = {
count: 1
}
foo.call(obj)
var bar = foo.bind(obj)
bar() // 1
- es6 绑定: 类似箭头函数创建成员变量,等于创建了没有挂载到原型链上的匿名函数,所以 this 不丢失
function foo() {
setTimeout(() => {
console.log(this.count)
})
}
var obj = {
count: 2
}
foo.call(obj) // count: 2
-
函数 bind: 指定回调函数作用域, 达到 this 指向正确原型链的效果
-
块级作用域 let const (warning: 不要忘记
if
下也有块级作用域)
- 不能因为绑定丢失引发非预期的报错避免使用,根本原因在于 js 的原型链机制和执行上下文机制,对象保存在原型链上方便多个实例之间共享,但是带来的原型链查找过程,如果对象运行环境法伤变化,原型链也会发生变化,所以带来两种做法: 一是使用 bind 显式绑定将原型链找到,而是偷懒将函数放在对象上, 不放在原型链上。