call,apply和bind

call和apply这两个方法都可以改变一个函数的上下文对象,只是接受参数的方式不一样,调用时会直接触发函数。

call接收的是逗号分隔的参数。

apply接收的是参数列表。

bind也可以改变函数的上下文对象,接收的是逗号分隔的参数,但是不会立刻触发函数,只会创建一个新的函数,在调用时设置this关键字为提供的值

 

例如

var arr = [1, 2, 3];
var max = Function.prototype.apply.call(Math.max, null, arr);
console.log(max); // 3

那么对这段代码怎么理解呢?

  1. 将Function.prototype.apply看成一个整体

(Function.prototype.apply).call(Math.max, null, arr)

   2. func.call(context, args)可以转化为context.func(args)

所以代码被转换为:

Math.max.apply(undefined, arr)

如果将call和apply交换位置呢

var arr = [1, 2, 3];
var max = Function.prototype.call.apply(Math.max, null, arr);
console.log(max); // -Infinity

为什么的它的输出结果为-Infinity呢?
因为apply的第二参数必须为数组,这里并不是,所以参数不能正确的传递给call函数。
根据func.apply(context, args)可以转化为context.func(args)。所以被转化成了Math.max.call(), 直接调用则会输出-Infinity。

如果想要正确调用,则应这样书写:

var arr = [1, 2, 3];
var max = Function.prototype.call.apply(Math.max, arr);
console.log(max); // 3

这里有一道面试题来巩固下

var a = Function.prototype.call.apply(function(a){return a;}, [0,4,3]);
alert(a); 

分析下

// 将call方法看成一个整体
(Function.prototype.call).apply(function(a){return a;}, [0,4,3]);
// func.apply(context, args)可以转化为context.func(...args)
(function(a){return a;}).call(0, 4, 3);
// 所以结果很明显,输出4

bind则和call的用法差不多,唯一区别是,call会立刻调用函数,bind只是绑定this

var arr = [1, 2, 3];
console.log(Math.max.call(...arr)); // 3
console.log(Math.max.bind(...arr)()) // 3

 

posted @ 2019-06-25 21:28  张石磊博客  阅读(622)  评论(0)    收藏  举报