call和apply改变了函数的this上下文后便执行该函数,而bind则是返回改变了上下文后的一个函数。
apply 方法,它让我们构造一个参数数组传递给函数,同时可以自己来设置 this 的值,这就是它最强大的地方,上面的 3 种函数调用方式,你可以看到,this 都是自动绑定的,没办法由你来设,当你想设的时候,就可以用 apply() 了。apply 函数接收 2 个参数,第一个是传递给这个函数用来绑定 this 的值,第二个是一个参数数组。看代码
function a(xx) {
this.b = xx;
}
var o = {};
a.apply(o, [5]);
alert(a.b); // undefined
alert(o.b); // 5
- 1
- 2
- 3
- 4
- 5
- 6
- 7
是不是很神奇,函数 a 居然可以给 o 加属性值。当然,如果你 apply 的第一个参数传递 null,那么在函数 a 里面 this 指针依然会绑定全局对象。
call() 方法和 apply() 方法很类似,它们的存在都是为了改变 this 的绑定,那 call() 和 apply() 有什么区别呢?!刚刚说了,上面 apply() 接收两个参数,第一个是绑定 this 的值,第二个是一个参数数组,注意它是一个数组,你想传递给这个函数的所有参数都放在数组里,然后 apply() 函数会在调用函数时自动帮你把数组展开。而 call() 呢,它的第一个参数也是绑定给 this 的值,但是后面接受的是不定参数,而不再是一个数组,也就是说你可以像平时给函数传参那样把这些参数一个一个传递。所以如果一定要说有什么区别的话,看起来是这样的
function a(xx, yy) {
alert(xx, yy);
alert(this);
alert(arguments);
}
a.apply(null, [5, 55]);
a.call(null, 5, 55);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
仅此而已。
bind() 函数
最后再来说 bind() 函数,上面讲的无论是 call() 也好, apply() 也好,都是立马就调用了对应的函数,而 bind() 不会, bind() 会生成一个新的函数,bind() 函数的参数跟 call() 一致,第一个参数也是绑定 this 的值,后面接受传递给函数的不定参数。 bind() 生成的新函数返回后,你想什么时候调就什么时候调,看下代码就明白了
var m = {
"x" : 1
};
function foo(y) {
alert(this.x + y);
}
foo.apply(m, [5]);
foo.call(m, 5);
var foo1 = foo.bind(m, 5);
foo1();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
末了来个吐槽,你在 js 里想定义一个函数,于是你会这么写:
function jam() {};
- 1
其实这是 js 里的一种语法糖,它等价于:
var jam = function() {};
- 1
然后你想执行这个函数,脑洞大开的你会这么写:
function jam() {}();
- 1
但是这么写就报错了,其实这种写法也不算错,因为它确实是 js 支持的函数表达式,但是同时 js 又规定以 function 开头的语句被认为是函数语句,而函数语句后面是肯定不会带 () 的,所以才报错,于是聪明的人想出来,加上一对括号就可以了。于是就变成了这样:
(function jam() {}());
- 1
这样就定义了一个函数同时也执行它。
参考:
1. https://blog.csdn.net/marcelwu/article/details/69057811
2. https://qianlongo.github.io/2016/04/26/js%E4%B8%ADcall%E3%80%81apply%E3%80%81bind%E9%82%A3%E4%BA%9B%E4%BA%8B/#more