JS & 改变 this 的三大利器:call / apply / bind

一、call

每个函数都有 call 方法,call 可以改变函数当前的 this 环境(对象),记住这点很重要。

例子1:给对象换新欢

const Jack = {
	hisGirlName: 'Candy',
	getMyGirlFriend() {
  		console.log(this.hisGirlName)
  	}
}
const John = {
	hisGirlName: 'Lili',
}
Jack.getMyGirlFriend.call(John) // 打印:Lili

例子2:偷天换日的感觉真是太棒了

function Jack() {}
Jack.prototype.bankAccount = '100'
Jack.prototype.getMyMoney = function() {
	console.log('Money:', this.bankAccount)
}

function Linda() {}
Linda.prototype.bankAccount = '100W';

const superPerson = new Jack()
console.log(superPerson.getMyMoney()) // 打印:100
console.log(superPerson.getMyMoney.call(new Linda)) // 打印:100W

二、apply

每个函数都有 apply 方法,它与 call 的作用是一模一样的,唯一的区别是,它的传参要用数组形式。

例子1:简化获取列表中的最值方式

const nums = [22,33,2,14,10,100]
const maxNum = Math.max.apply(null, nums)
const minNum = Math.min.apply(null, nums)
console.log(maxNum, minNum) // 打印:100 2

提示:apply 第二个参数虽是数组形式,但函数接受时是以单个参数形式,理清这点是有必要的,这也是 Math.max 能够识别“数组”参数的原因。

例子2:给对象换新欢

和 call 一样,这里就不举例了。

三、bind

每个函数都有 bind 方法,它与前面的 call/apply 不同,它并不会立即调用函数,而是返回一个新的函数(通常也叫偏函数)并绑定调用时的传递的 this 执行环境 记住这点很重要。

例子1:先存起来,下次再用

for (var i = 0; i < 5; i ++) {
	var self = this
 	setTimeout(function(num) {
		console.log(num)
	}.bind(self, i), 1000)
}
// 打印:0 1 2 3 4

解释:bind 绑定了当前所属环境,这里的 i 是按值传参,于是,bind 每次绑定的值便是 i 当前的那个值。当每个定时器执行后将读取当前所处环境的参数值。

利用传参是按值传递的特性,上面的代码也可以改成这样的:

for (var i = 0; i < 5; i ++) {
	var fn = function(num) { return function() { console.log(num) } }
	setTimeout(fn(i), 1000)
}

四、留意

  1. call/applybind 传递指向环境非 this 而是 null 时,此时 null === windows 全局环境。
  2. call/apply/bind 可以混合使用。

你可能感兴趣的:(JavaScript,javascript,开发语言,ecmascript)