首页 > 代码库 > JavaScript中的call()、apply()与bind():
JavaScript中的call()、apply()与bind():
关于call()与apply():
在JavaScript中,每个函数都有call与apply(),这两个函数都是用来改变函数体内this的指向,并调用相关的参数。
看一个例子:
定义一个animal对象,该对象有一个jump()方法:
var animal = { type:‘animal‘, jump:function(name){ return this.type + ‘ is ‘ + name; } } some_animal.jump(‘dog‘); **"animal is dog"**
如果这个时候有一个对象other_animal对象,只有一个type属性:
var other_animal = { type:‘other animal‘ }
这种情况下也要调用animal的jump()方法,这时候就可以用到jump()函数中的call()。
one_animal.jump.call(other_animal,‘cat‘). **"other animal is cat"**
当jump被调用时,其中的this被设置成为了other_animal对象的引用,所以this.type返回的是other animal。
当有多个参数的时候,
one_animal.method.call(other_animal,‘cat‘,‘mouse‘).
apply()与call()基本相同,唯一的不同是参数的传递形式。
apply()传递的是一个数组。
如下两行是等效的:
one_animal.method.call(other_animal,‘cat‘,‘mouse‘). one_animal.method.call(other_animal,[‘cat‘,‘mouse‘]).
分享一道题目:
定义一个 log 方法,让它可以代理 console.log 方法。
常见解决方案:
function log(msg) { console.log(msg); } log(1); //1 log(1,2); //1
当传入参数不确定时,上述方法就失效了。便可考虑用apply()或call(),这里参数个数不确定,用apply()更好。
function log(){ console.log.apply(console, arguments); }; log(1); //1 log(1,2); //1 2
关于bind():
bind()的用法跟call()与apply()的用法很相似,都是改变函数体内this的指向。
MDN的解释是:bind()方法会创建一个新函数。当这个新函数被调用时,bind()的第一个参数将作为它运行时的 this, 之后的一序列参数将会在传递的实参前传入作为它的参数。
this.x = 9; var module = { x: 81, getX: function() { return this.x; } }; module.getX(); // 返回 81 var retrieveX = module.getX; retrieveX(); // 返回 9, 在这种情况下,"this"指向全局作用域 // 创建一个新函数,将"this"绑定到module对象 // 新手可能会被全局的x变量和module里的属性x所迷惑 var boundGetX = retrieveX.bind(module); boundGetX(); // 返回 81
在常见的单体模式中,通常会使用_this,that,self等来保存this,为了在改变了上下文环境之后能够继续使用它们。
var func = { num:1, event:function(){ var that = this; $(‘.class‘).click(function(){ console.log(that,num); }) } } //用bind()来改变this: var func = { num:1, event:function(){ $(‘.class‘).click(function(){ console.log(this,num); }.bind(this)) } }
在这里,click被调用时,this被设置成传入的值。当回调函数执行时,this便指向func对象。
more example: var method = function(){ console.log(this.x); } method();//undefined var method_func = method.bind(func); method_func();
注意:
在JavaScript中多次使用bind()是无效的。
原因是,bind()的实现,相当于在使用函数内部包了一个call/apply,第二次bind()相当于再包住一次bind(),所以无效。
比较apply、call、bind:
var method = { x: 3, }; var func= { getX: function() { return this.x; } } console.log(func.getX.bind(method)()); //3 console.log(func.getX.call(method)); //3 console.log(func.getX.apply(method)); //3
JavaScript中的call()、apply()与bind():