Skip to content

Latest commit

 

History

History
86 lines (64 loc) · 2.57 KB

13.This带来的困惑.md

File metadata and controls

86 lines (64 loc) · 2.57 KB

013.This 带来的困惑.md

避免使用 this

  • 初学者 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 丢失情况

  • 默认绑定,区分严格模式和非严格模式,严格模式下 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

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下也有块级作用域)

summary

  • 不能因为绑定丢失引发非预期的报错避免使用,根本原因在于 js 的原型链机制和执行上下文机制,对象保存在原型链上方便多个实例之间共享,但是带来的原型链查找过程,如果对象运行环境法伤变化,原型链也会发生变化,所以带来两种做法: 一是使用 bind 显式绑定将原型链找到,而是偷懒将函数放在对象上, 不放在原型链上。