前言
本篇文章主要是巩固基础,对ES6新增修改this指向的方法做一个总结。
正文
话不多说,我们直接进入主题。
语法:call(thisArg, arg1, arg2, /* …, / argN)
语法:apply(thisArg, argsArray)
语法:bind(thisArg, arg1, arg2, / …, */ argN)
代码示例👇👇:
let dog1 = {
name: '胖胖',
age: '4',
say: function(food, drink) {
console.log(`my name is ${this.name}, ${this.age} years old, eat ${food},
drink ${drink}`, this === dog1, this === dog2)
}
}
let dog2 = { name: '壮壮', age: 2 }
dog1.say('狗粮', 'Lafite')
dog1.say.call(dog2, '骨头', 'cola', 'other')
dog1.say.apply(dog2, ['肉', 'bohea', 'other'])
dog1.say.bind(dog2, '馒头', 'milk', 'other')()
dog1.say.bind(dog2)('馒头-1', 'milk-1', 'other-1')
以上代码输出为:
总结
· 三者都可以改变函数内部 this 的指向;
· call()改变了this的指向,指向了第一个参数thisArg,剩余参数就是作为对应函数的参数使用,并且函数自动执行,返回值就是函数的返回值;
· apply()与call()的区别就在于,函数的参数是以数组的形式来进行传参;
· call apply 都是立即调用;
· bind()与call()的区别就在于,bind()会创建一个新的函数,以这个新函数为返回值,并不会自动执行, 另外我们可以在绑定this指向的时候进行传参,也可以选择执行的时候进行传参。
手写实现
call()的实现
首先我们已经了解,三者都可以改变函数内部 this 的指向为绑定的对象,其次都可以传入参数,那么我们就针对于这两者进行封装。
Function.prototype.my_call = function() {
// 解构arguments,获取绑定对象和参数
const [thisArg, ...args] = arguments
// 确保key的唯一防止与绑定对象属性冲突。
const key = Symbol()
// this 为当前执行函数,利用this的隐式绑定,将 say 函数中的 this 绑定到 thisArg 中
thisArg[key] = this
// 执行函数并返回结果
const result = thisArg[key](...args)
// 移除属性 防止污染绑定对象
delete thisArg[key]
// 返回结果
return result
}
apply()的实现
apply 与 call 的区别在于传入参数的类型,只需要在 my_call 上稍作修改即可
Function.prototype.my_apply = function() {
const [thisArg, arg] = arguments
const key = Symbol()
thisArg[key] = this
const result = thisArg[key](...arg)
delete thisArg[key]
return result
}
bind()的实现
bind 与 call 的区别在于,bind会创建一个新的函数,以这个新函数为返回值,不执行。
Function.prototype.my_bind = function() {
const [thisArg, ...args] = arguments
const key = Symbol()
thisArg[key] = this
return function(...args1) {
const result = thisArg[key](...args, ...args1)
delete thisArg[key]
return result
}
}
接下来我们做一个验证:
let dog1 = {
name: '胖胖',
age: '4',
say: function(food, drink) {
console.log(`my name is ${this.name}, ${this.age} years old, eat ${food},
drink ${drink}`, this === dog1, this === dog2)
}
}
let dog2 = { name: '壮壮', age: 2 }
dog1.say('狗粮', 'Lafite')
dog1.say.my_call(dog2, '骨头', 'cola', 'other')
dog1.say.my_apply(dog2, ['肉', 'bohea', 'other'])
dog1.say.my_bind(dog2, '馒头', 'milk', 'other')()
dog1.say.bind(dog2)('馒头-1', 'milk-1', 'other-1')
至此,本篇完!!!