这三个方法都是继承自Function.prototype中,属于实例方法。普通对象都继承了这些方法。
1.call():demo.call(obj,[参数],[参数])
将参数一一进行传递(函数中的this指向obj,并执行函数)
2.apply():demo.apply(obj,[参数数组]);
将demo需要的参数以数组的形式传递,(函数中的this指向obj,并执行函数)
以上这两种方法只有调用的这行代码改变指向,不影响原函数的this指向
3.bind():使用方法与call相同,传参方式相同,但不会立即执行函数,而是返回一个新函数,新函数中的this指向改变,不影响原函数的this指向
源码实现
// call()
Function.prototype.myCall = function() {
var target = arguments[0] || window //arguments[0]是要指向的对象,保存要指向的对象,不传值则指向window
var arg = Array.from(arguments).slice(1) //将arguments转换为真数组,然后截取数组,因为0是要指向的对象,所以从1开始截取
target.fn = this; //给要指向的对象添加了一个fn属性,值为this,这个this的值为调用myCall的函数
target.fn(...arg) //用这个对象调用fn,fn函数内部this就指向target了
}
//apply()
//apply()实现与call差不多,但是apply接收参数是一个数组,所以改变上面第二步即可
Function.prototype.myApply = function() {
var target = arguments[0] || window
var arg = Array.from(arguments[1]) //直接保存传进来的数组
target.fn = this;
target.fn(...arg)
}
//bind()
//bind()与call相似,但bind返回的是一个新数组
Function.prototype.myBind = function() {
var target = arguments[0] || window
var arg = Array.from(arguments).slice(1)
var self = this //保存this,==>调用myBind的函数
return function() { //返回一个新函数
var arg1 = Array.from(arguments) //新函数可以继续传参,保存新函数传进的参数
target.fn = self
target.fn(...(arg.concat(arg1))) //拼接两次传递的参数
}
}