call,apply,bind相同点都是改变this指向,指向传入的thisObj的上下文环境。
不同点
对于第二个参数,call参数必须一一列举出来,apply传入的是一个argment对象或者数组,bind①bind的返回值是函数;②后面的参数的使用也有区别。
1、call方法:
语法:call([thisObj,[,arg1[, arg2[, [,.argN]]]]])
定义:调用一个对象的一个方法,以另一个对象thisObj替换当前对象。
说明:call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj指定的新对象。
如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。
function sum(num1,num2){
return num1+num2;
}
function callSum(num1,num2){
//将sum函数调用到当前callSum环境下执行,并传入sum函数需要的参数
return sum.call(this,num1,num2);
}
console.log(callSum(20,20));
2、apply:
语法:apply(thisObj,数组参数)
定义:应用某一个对象的一个方法,用另一个对象thisOb替换当前对象
说明:如果参数不是数组类型的,则会报一个TypeError错误。
function sum(num1,num2){
return num1+num2;
}
function applySum1(num1,num2){
return sum.apply(this,[num1,num2]);
}
function applySum2(num1,num2){
return sum.apply(this,arguments);
}
console.log(applySum1(30,20));
console.log(applySum2(10,20));
3、bind:
在EcmaScript5中扩展了叫bind的方法(IE6,7,8不支持),bind与call很相似,,例如,可接受的参数都分为两部分,且第一个参数都是作为执行时函数上下文中的this的对象。手写一个自定义的bind函数,如下:
不清楚this指向的可以点击查看阮一峰老师的博文
Function.prototype.customeBind2 = function(thisObj,...list){
let self = this;//目标函数
console.log(this);//this指向下面的函数fun,即返回的新函数
let Bound = function(...arg2){
// 如果这个函数作为了构造函数,那么目标函数的this,应该执行的是实例对象
// 如果这个不是作为构造函数,目标函数中的this还指向thisArg
let thisArgSelf = this instanceof Bound ? this : thisArg;
self.apply(thisArgSelf,[...list,...arg2])
}
// 原型继承
// Object.create 用来创建以某一个对象作为原型的对象的
Bound.prototype = Object.create(self.prototype);
Bound.prototype.constructor = self;
// 返回的新函数
return Bound
}
/**this打印的新函数为
ƒ func(...arg){
console.log(this);//this指向{a:1}
console.log(arg)
}
*/
function fun(...arg){
console.log(this);
console.log(arg);
}
/**控制台打印如下
{b: 2}
(6) [99, 9, 33, 3, 4, 2]
-------------------
{b: 3}
(5) [99, 3, 22, 9, 3]
*/
//this指向b,返回的新函数为fun1,需要执行这个函数
let fun1 = fun.bind({b:2},99,9,33);
let fun2 = fun.customeBind2({b:3},99,3,22);
fun1(3,4,2);
console.log('-------------------')
fun2(9,3);
分析结束,参考资料《JavaScript高级程序设计》