三者的相同点:都是用来改变this的指向
1.call()和apply()的区别:
都是调用一个对象的一个方法,用另一个对象替换当前对象(功能相同)
B.call(A, args1,args2);即A对象调用B对象的方法
F.apply(G, arguments);即G对象应用F对象的方法
相同点:第一个参数是this要指向的对象,当第一个参数为null、undefined时,默认指向window;
不同点:apply()第二个参数是数组,call()是参数列表
2.与bind()的区别:
call和apply在改变方法的this指向时,会同时执行方法;而bind不会执行方法,而是返回改变this指向后的新方法
var x = "window_x";
var obj = {
x : "obj_x",
fn : function(y){
console.log(this.x + " ; " + y);
}
}
obj.fn(1); //obj_x ; 1
var fn = obj.fn;
fn(1); //window_x ; 1
fn.call(obj,1); //obj_x ; 1
fn.apply(obj,[1]); //obj_x ; 1
fn.bind(obj,1); //返回fn方法:f (y){console.log(this.x + " ; " + y);}
var bfn = fn.bind(obj);
bfn(1); //obj_x ; 1
执行结果:
3.常见用法:
3.1 利用apply()求最大值
var arr =[2,6,8,3,4,9,7,23,56,889];
console.log(Math.max.apply(null,arr))
console.log(Math.max.apply(arr,arr))
//第一个arr表示让arr借用max这个方法,第二个arr表示传给max的数据
//apply()所执行的操作:1.执行Math.max(1,2,3,5,4) 2.把内部的this改成arr
4.手写call():
Function.prototype.newcall = function(par){
//有参用参,无参指向window
par = par || window;
//添加一个属性 赋值给this
par.fn = this;
//arguments [function,参数] 截取参数 为从funciton后的形成新的数组[par];
var arg = [...arguments].slice(1);
//将数组作为入参给定义的 调用方法 ...arg将arg转为用逗号分隔的参数序列
var result = par.fn(...arg);
//原来par是没有fn的,删除掉,不影响继承结构
delete par.fn;
return result;
};
5.手写apply():
// 思路:将要改变this指向的方法挂到目标this上执行并返回
Function.prototype.myapply = function (ctx) {
ctx = ctx||window;
ctx.fn = this;
var result;
//arguments 此时为 [fn ctx(),[参数];
if(arguments[1]){
//[参数]对应apply传的数组
result =ctx.fn(...arguments[1]);
}else{
result =ctx.fn();
}
delete ctx.fn;
return result;
}
验证方法是否生效:
function add(a,b){
return a+b;
}
function sub(a,b){
return a - b;
}
console.log(add.newcall(sub,10,15));
console.log(add.myapply(sub,[10,20]));