call、apply、bind都是用来改变this指向的,区别在于call和apply是立即执行的,而bind需要再次调用。
call
Function.prototype.myCall = function(context){
//先判断调用myCall是不是一个函数
//这里的this就是调用myCall的
if(typeof this !== 'function'){
throw new TypeError('Not a Function')
}
//不传参数默认为window
context = context||window
//保存this
context.fn = this
//保存参数
const args = [...arguments].slice(1) //当一个参数为context,去除
//调用函数
const result = context.fn(...args)
delete context.fn
return result
}
apply
//apply
Function.prototype.myApply = function (context) {
// 判断this是不是函数
if (typeof this !== "function") {
throw new TypeError("Not a Function")
}
let result
// 默认是window
context = context || window
// 保存this
context.fn = this
// 是否传参
if (arguments[1]) {
result = context.fn(...arguments[1])
} else {
result = context.fn()
}
delete context.fn
return result
}
bind
Function.prototype.myBind = function(context){
// 判断是否是一个函数
if(typeof this !== "function") {
throw new TypeError("Not a Function")
}
// 保存调用bind的函数,返回一个绑定this的函数
const _this = this
// 保存参数
const args = [...arguments].slice(1)
// 返回一个函数
return function F () {
// 判断是不是new出来的
if(this instanceof F) {
// 如果是new出来的
// 返回一个空对象,且使创建出来的实例的__proto__指向_this的prototype,且完成函数柯里化
return new _this(...args,...arguments)
}else{
// 如果不是new出来的改变this指向,且完成函数柯里化
return _this.apply(context,args.concat(...arguments))
}
}
}