目录
前言
call,apply,bind改变this指向 面试官最喜欢考的题
一、call实现
只要搞清楚this是什么情况就容易理解
function Person(name, price) {
this.name = name
this.price = price
this.msg = function () {
console.log('我叫' + this.name)
}
}
let arg = {
sex: '男',
age: 20
}
// 向原型添加一个方法 使所有的函数都可以用此方法
// thisArg(需要被添加属性或方法的对象)...arg(接受的参数)
Function.prototype.myCall = function (thisArg = globalThis, ...arg) {
//添加一个独一无二的值 以免thisArg里面有一样名字的属性会被覆盖掉
const key = Symbol()
//这个this指向他的调用者this为asg 调用myCall的函数里面的this会变成thisArg
thisArg[key] = this
// 将函数里面的形参赋值
thisArg[key](...arg)
// 删除多余都属性
delete thisArg[key]
//call的返回值是undefined
return thisArg
}
console.log(Person.myCall(arg, '祁纤', '10000'))
二、apply实现
跟call同理
注意...运算符的使用
// 向原型添加一个方法 使所有的函数都可以用此方法
// thisArg(需要被添加属性或方法的对象)...arg(接受的参数)
Function.prototype.myApply = function (thisArg, arg) {
// 如果thisArg不是很法值就返回对应环境的全局 如Window
if (!thisArg) {
thisArg = globalThis
}
arg= arg? arg: []
//添加一个独一无二的值 以免thisArg里面有一样名字的属性会被覆盖掉
const key = Symbol()
//这个this指向他的调用者this为asg 调用myCall的函数里面的this会变成thisArg
thisArg[key] = this
// 将函数里面的形参赋值
thisArg[key](...arg)
// 删除多余都属性
delete thisArg[key]
//apply的返回值是undefined
return thisArg
}
console.log(Person.myApply(arg, ['祁纤', '10000']))
三、bind实现
,bind是返回一个绑定好的函数,就是返回一个函数,要考虑到使用new去调用,并且new的优先级比较高,所以需要判断new的调用,还有一个特点就是bind调用的时候可以传参,调用之后生成的新的函数也可以传参,效果是一样的,所以这一块也要做处理 因为上面已经实现了apply,这里就借用一下,实际上不借用就是把代码copy过来
let obj = {
name: '祁纤',
fun() {
return this.name
}
}
function Fun(bzd) {
this.bzd = bzd
}
Function.prototype.myBind = function (context, ...args) {
// // 保存一下this,防止this丢失
let self = this
// 以后函数可以传参...fnArgs
return function fn(...fnArgs) {
// instanceof用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
// new 的时候,this指向new出来的实例,实例的__proto__指向fn的prototype
if (this instanceof fn) {
// 让this指向被new 出来的实例对象
return new self(...args, ...fnArgs)
}
return self.apply(context, [...args, ...fnArgs])
}
}
let fun = Fun.myBind(obj, '呜呜呜')
fun()
console.log(obj)
以上所有实现可以再加点判断啊,例如调用的不是function就返回或者抛出错误啊之类的.我这里就不处理了
以上就是apply,call,bind的实现了
特点区别
call() 方法使用一个指定的this值和单独给出的一个或多个参数来调用一个函数。
apply() 方法使用一个指定的this值和单独给出的 一个或多个参数的数组 来调用一个函数。
bind()
方法创建一个新的函数,在 bind()
被调用时,这个新函数的 this
被指定为 bind()
的第一个参数,而其余参数将作为新函数的参数,供调用时使用。