call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。
apply() 方法调用一个具有给定this值的函数,以及作为一个数组(或类似数组对象)提供的参数。
bind()方法创建一个新的函数,在bind()被调用时,这个新函数的this被bind的第一个参数指定,其余的参数将作为新函数的参数供调用时使用。
三者的相似之处:
1、都是用来改变函数的this对象的指向的。
2、第一个参数都是this要指向的对象。
3、都可以利用后续参数传参。
注意:call()方法的作用和 apply() 方法类似,区别就是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组。
语法:
call:fun.call(thisOject, arg1, arg2, ...)
apply:func.apply(thisOject, [argsArray])
bind:function.bind(thisOject[,arg1[,arg2[, ...]]])
一个小示例来解释三者的不同
function fn1(height){console.log(`姓名:${this.name},年龄:${this.age},身高:${height}`)}
var obj = {name:'李四',age:35}
fn1(180); // 姓名:undefined,年龄:undefined,身高:180
// call
fn1.call(obj,180); // 姓名:李四,年龄:35,身高:180
// apply
fn1.apply(obj,[180]); // 姓名:李四,年龄:35,身高:180
// bind
fn1.bind(obj,180)(); // 姓名:李四,年龄:35,身高:180
1.Function.prototype.call()
语法:fun.call(thisOject, arg1, arg2, ...)
参数:
thisOject:在 fun 函数运行时指定的 this 值。
if(thisOject== undefined|null) {this = window}
if(thisOject== number|boolean|string){ this == new Number()|new Boolean()| new String()}
arg1, arg2, ...指定的参数列表。
call() 允许为不同的对象分配和调用属于一个对象的函数/方法。
call() 提供新的 this 值给当前调用的函数/方法。可以使用 call 来实现继承:写一个方法,然后让另外一个新的对象来继承它(而不是在新对象中再写一次这个方法)。
示例:
实现继承:
/* 不使用继承,fn2使用fn1里面的属性 */
function fn1(name){this.name =name;this.sex ='女';}
function fn2(){this.age = 20;}
var f2 = new fn2();
console.log(f2.name);'// undefined
console.log(f2.sex);'// undefined
/* 使用call继承fn1 */
function fn1(name){this.name =name;this.sex ='女';}
function fn2(){fn1.call(this,'张三');this.age = 20;}
var f2 = new fn2();
console.log(f2.name); //"张三"
console.log(f2.sex); //"女"
实现调用函数并且指定上下文的 'this'
function fn1(height){console.log(`姓名:${this.name},年龄:${this.age},身高:${height}`)}
var obj = {name:'李四',age:35}
fn1(180); // 姓名:undefined,年龄:undefined,身高:180
fn1.call(obj,180); // 姓名:李四,年龄:35,身高:180
2.Function.prototype.apply()
apply 与 call() 非常相似,不同之处在于提供参数的方式。apply 使用参数数组而不是一组参数列表。apply 可以使用数组字面量(array literal),如 fun.apply(this, ['eat', 'bananas']),或数组对象, 如 fun.apply(this, new Array('eat', 'bananas'))。
例如上面的案例使用apply的话:
function fn1(height){console.log(`姓名:${this.name},年龄:${this.age},身高:${height}`)}
var obj = {name:'李四',age:35}
fn1(180); // 姓名:undefined,年龄:undefined,身高:180
fn1.call(obj,180); // 姓名:李四,年龄:35,身高:180
// apply
fn1.apply(obj,[180]); // 姓名:李四,年龄:35,身高:180
语法:func.apply(thisOject, [argsArray])
参数:
thisOject:可选的。在 func 函数运行时使用的 this 值。请注意,this可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动替换为指向全局对象,原始值会被包装。
argsArray:可选的。一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 func 函数。如果该参数的值为 null 或 undefined,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。 浏览器兼容性 请参阅本文底部内容。
拓展
用 apply 将数组添加到另一个数组
var arr1 = ['张三', '李四'];
var arr2 = [0, 1, 2];
arr1.push.apply(arr1, arr2);
console.log(arr1 ); // ["张三", "李四", 0, 1, 2]
使用apply
和内置函数
var arr = [4, 5, 1, 2, 6];
Math.max(...arr); // 6
Math.max.apply(null, arr); // 6
但是当心:如果用上面的方式调用apply
,会有超出JavaScript引擎的参数长度限制的风险。当你对一个方法传入非常多的参数(比如一万个)时,就非常有可能会导致越界问题, 这个临界值是根据不同的 JavaScript 引擎而定的