js中bind,call,apply的作用以及模拟实现
apply的实现
apply的特点
- 只有两个参数 第一个参数是需要指向的对象 使用一个数组来作为该函数的第二个参数
- 没有传入参数就默认指向window
Function.prototype.myApply = function(context){
context = context ? Object(context) : window; //
let fn = Symbol()
context[fn] = this // this是当前调用了call的函数
let res = context[fn](...arguments[1]) //执行函数
delete context[fn]
return res
}
let obj1 = {
test(a,b,c){
console.log(this,a,b)
}
}
obj1.test.myApply(obj1,[4,5])// { test: [Function: test], [Symbol()]: [Function: test] } 4 5
call的实现
call的特点
- call其实是apply的一个语法糖,他们的作用都是用于改变上下文的指向,区别在于,call接受多个参数,而apply接受的是一个数组
// call的实现
Function.prototype.myCall = function(context,...rest){
context = context ? Object(context) : window; //
let fn = Symbol()
context[fn] = this // this是当前调用了call的函数
let args = rest // 剩余参数数组
let res = context[fn](...args) //执行函数
delete context[fn]
return res
}
let obj1 = {
test(a,b,c){
console.log(this,a,b)
}
}
obj1.test.myCall(obj1,4,5) // { test: [Function: test], [Symbol()]: [Function: test] } 4 5
bind的实现
- bind的实现与call类似 只是返回改变了this指向的函数,并不执行
Function.prototype.myBind = function(context){
if(typeof this != 'function') {
throw new TypeError('Error');
}
let _this = this;
let args = [...arguments].slice(1);//拿到传入的参数
return function F() {
if(this instanceof F) { // 判断this在F的原型链上没
return new _this(...args,...arguments);
}
return _this.apply(context,args.concat(...arguments))
}
}
obj1.test.myBind(obj1,4,5)() // { test: [Function: test] } 9