call() 、apply()可以看作是某个对象的方法,通过调用方法的形式来间接调用函数。bind() 就是将某个函数绑定到某个对象上。
如:
var obj = { name : 'zhangsan' } function getName() { console.log(this.name); } //call和apply的会立即执行 getName.call(obj); //zhangsan getName.apply(obj); //zhangsan //bind则返回一个新的函数 var new_fun = getName.bind(obj); new_fun(); //zhangsan
当你希望改变上下文环境之后并非立即执行,而是回调执行的时候,使用 bind() 方法。而 apply/call 则会立即执行函数。
1.call()和apply()的相同点和区别
相同点:第一个参数相同,就是指定的对象。这个对象就是该函数的执行上下文。
区别:call()在第一个参数之后的 后续所有参数就是传入该函数的值。
apply() 只有两个参数,第一个是对象,第二个是数组,这个数组就是该函数的参数。
例:
var obj = { name : 'zhangsan' } function getName(str1,str2) { console.log(str1+','+this.name+','+str2); } getName.call(obj,'hello','js难吗?'); //hello,zhangsan,js难吗? getName.apply(obj,['hello','js难吗?']); //hello,zhangsan,js难吗?
2. 深入理解运用apply、call
定义一个 log _方法,让它可以代理 console.log 方法,常见的解决方法是:
function log_(msg) { console.log(msg); } log_('nihao'); //nihao log_('nihao','world'); //nihao
上面方法可以解决最基本的需求,但是当传入参数的个数是不确定的时候,上面的方法就失效了,这个时候就可以考虑使用 apply 或者 call,注意这里传入多少个参数是不确定的,所以使用apply是最好的,方法如下:
function log_() { console.log.apply(console,arguments); } log_('nihao'); //nihao log_('nihao','world'); //nihao world
接下来的要求是给每一个 log 消息添加一个"(app)"的前辍。这个时候需要想到arguments参数是个伪数组,通过 Array.prototype.slice.call 转化为标准数组,再使用数组方法unshift,像这样:
function log_() { var args = Array.prototype.slice.call(arguments); //将arguments转换成标准的数组 args.unshift('(app)'); console.log.apply(console,args); } log_('nihao'); //(app) nihao log_('nihao','world'); //(app) nihao world