JavaScript——函数调用 call()、apply()、bind()
立即调用(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 则会立即执行函数。
总结:
- apply 、 call 、bind 三者都是用来改变函数的this对象的指向的;
- apply 、 call 、bind 三者第一个参数都是this要指向的对象,也就是想指定的上下文;
- apply 、 call 、bind 三者都可以利用后续参数传参;
- bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用 。