立即调用(call now)
在 javascript
中,call
和 apply
都是为了改变某个函数运行时的上下文(context)而存在的,换句话说,就是为了改变函数体内部 this 的指向。
JavaScript 的一大特点是,函数存在「定义时上下文」和「运行时上下文」以及「上下文是可以改变的」这样的概念。
区别:作用一样,接受参数的方式不一样
其中 this 是你想指定的上下文,他可以是任何一个 JavaScript 对象(JavaScript 中一切皆对象),call 需要把参数按顺序传递进去,而 apply 则是把参数放在数组里。
例如有一个函数定义如下
let fun = function(arg1,arg2){}
call()
传参
fun.call(this,arg1,arg2)
apply()
传参
fun.apply(this,[arg1,arg2])
实例demo
获取数组中的最大值和最小值
var numbers = [5, 458 , 120 , -215 ];
var maxInNumbers = Math.max.apply(Math, numbers), //458
maxInNumbers = Math.max.call(Math,5, 458 , 120 , -215); //458
- PS:number 本身没有 max 方法,但是 Math 有,我们就可以借助 call 或者 apply 使用其方法。
新建函数(new function)
bind()
bind()
方法创建一个新的函数,在bind()
被调用时,这个新函数的 this
被指定为 bind()
的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
- 在Javascript中,多次 bind() 是无效的。
let a = function(){}
let b = a
console.log(a==b); // true
let c = a.bind() // 新复制的函数,所以会和原来的不一样
console.log(a==c); // false
通常我们会使用 _this ,
that,
self 等保存
this `,这样我们可以在改变了上下文之后继续引用到它。
例如这样:
var foo = {
num: 1,
change: function(){
let_this = this;
$('.btn').on('click',function(event) {
console.log(_this.num); //1
});
}
}
如果不使用常量保存this
的话,this
将会指向window
而不是foo函数。
可以使用bind()
更加优雅的解决这个问题
var foo = {
num: 1,
change: function(){
$('.btn').on('click',function(event) {
console.log(this.num); //1
}.bind(this));
}
}
在上述代码里,bind() 创建了一个函数,当这个click事件绑定在被调用的时候,它的 this
关键词会被设置成被传入的值(这里指调用bind()
时传入的参数)。因此,这里我们传入想要的上下文this
(其实就是 foo ),到 bind() 函数中。然后,当回调函数被执行的时候, this 便指向 foo 对象。
demo
let bar = function(){
console.log(this.x);
}
letfoo = {
x:3
}
bar(); // undefined
bar.bind(foo)(); // 3
这里我们创建了一个新的函数 func,当使用 bind()
创建一个绑定函数之后,它被执行的时候,它的this
会被设置成 foo , 而不是像我们调用 bar() 时的全局作用域。
call、apply、bind比较
demo1:
var obj = {
x: 81,
};
var foo = {
getX: function() {
return this.x;
}
}
console.log(foo.getX.bind(obj)()); //81
console.log(foo.getX.call(obj)); //81
console.log(foo.getX.apply(obj)); //81
三个输出的都是81,但是注意看使用 bind()
方法的,他后面多了对括号。
也就是说,区别是,当你希望改变上下文环境之后并非立即执行,而是回调执行的时候,使用 bind()
方法。而 apply
/call
则会立即执行函数。
总结:
1、apply 、 call 、bind 三者都是用来改变函数的this对象的指向的;
2、apply 、 call 、bind 三者第一个参数都是this要指向的对象,也就是想指定的上下文;
3、apply 、 call 、bind 三者都可以利用后续参数传参;
4、bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用 。