首先我们先说一下这三个方法是干什么的?
- call 和 apply 是为了改变某个函数运行时的上下文(context)。意思就是为了改变函数内部的this指向。
- bind方法的主要作用是将函数绑定到一个对象上,并返回一个函数,作为指定对象的方法执行该函数,bind方法可传递参数。
使用:
function a(arg){
console.log(this.name,"我的参数是" + arg)
}
const obj = {
name:"我是对象"
}
a.call(obj,"call"); // 我是对象 我的参数是call
a.apply(obj,["apply"]); // 我是对象 我的参数是apply
a.bind(obj,"")(); // 我是对象 我的参数是bind
那么他们有什么区别呢?
- call方法的第一个参数是要绑定给this的值,默认是window。后边接受一个参数列表。
- apply方法接受两个参数,第一个参数是要绑定给this的值,默认值也是window,第二个参数是一个参数数组。
- bind方法 第一个参数要绑定给this的值,后边的参数是参数列表。区别在于bind方法返回值是函数。
- call和apply方法会直接执行该函数,bind方法不会直接执行。
接下来我们手写实现三个方法
call方法的实现:
Function.prototype.call(newThis,...arg){
const newThis.fn = this;// 这样写有一个问题 那就是可能覆盖原有属性fn
return newThis.fn(...arg)
}
Function.prototype.call(newThis = window,...arg){
// 我们还需要给newThis 一个默认值,如果没有传递this 默认就是window
const fn = Symbol('fn'); // 我们声明一个独一无二的属性
return newThis[fn](...arg)
}
apply方法的实现:
apply方法的实现方法和call方法差不多,需要注意的就是参数传递的问题
Function.protptype.apply(newThis = window,arg){
// 我们还需要给newThis 一个默认值,如果没有传递this 默认就是window
const fn = Symbol('fn'); // 我们声明一个独一无二的属性
return newThis[fn](...arg)
}
bind方法的实现:
Function.prototype.bind(newThis,...arg){
const that = this;
const newFunction = function (){
const self = this instanceof that ? this : thisArg;// 保证this的指向
that.apply(self,arg.concat(Array.prototype.slice.call(arguments)));
// newBind函数还可以接受参数,所以需要把newBind函数的参数和原函数的参数合并在一起
}
// 还需要继承原型上的属性和方法
Function.prototype = Object.create(self.prototype);
return newFunction
}
网友评论