手写call、apply、bind
手写call
Function.prototype.mycall = function(context, ...argus){
//this指调用的那个函数
if(typeof this !== 'function') throw new Error()
context = context || window
//在指定的对象中添加fn属性,属性值为调用的函数,这个时候this的指向就转到了这个指定的对象中
context['fn'] = this
const res = content['fn'](...argus)
delete context['fn']
return res
}
手写apply
Function.prototype.myapply = function(context, argus){
if(typeof this !== 'function') throw new Error()
context = context || window
context['fn'] = this
const res = context['fn'](...argus)
delete context['fn']
return res
}
手写bind
Function.prototype.mybind = function(){
if(typeof this !== 'function') throw new Error()
let argus = Array.prototype.slice.call(arguments)
let context = argus.splice(0,1)[0]
let self = this
const res = function(){
let arr = Array.prototype.slice.call(arguments)
//这个this是res函数里的this,判断调用的是不是以new的形式
if(this instanceof res){
//如果是new的形式,this变成res的this
return this.apply(context, argus.concat(arr))
}else{
//如果不是,就是外面传的this
return self.apply(context, argus.concat(arr))
}
if(this.prototype) res.prototype = this.prototype
return res
}
}
手写bind需要处理通过new创建实例的情况。我们在new一个实例时会发生以下几个步骤:
- 创建一个空对象{}
- 实例的__proto__等于构造函数原型对象prototype
- 函数中的this设置为这个空对象。使用新对象调用函数,函数中的this被指向新实例对象
{}.构造函数()
- 如果该函数不返回一个对象,就返回这个 this,否则返回这个对象
因此,判断是不是通过new来创建的方法为
//this instanceof Fn
function Person() {
if (this instanceof Person) {
console.log('通过 new 构建实例');
} else {
console.log('普通调用')
}
}
Person() // 输出:普通调用
new Person() // 输出:通过 new 构建实例
参考文章:
https://juejin.cn/post/7172412939989680158
https://blog.csdn.net/fe_watermelon/article/details/125700486