js之call() apply() bind() $proxy()的总结
关于this的使用
先贴一段代码.
window.name = 'window'; var obj = { name:'I' } function foo(name,sex){ setTimeout(function(){ console.log(this.name+' love '+name+' cause '+name+' is a '+sex); },100); } //foo('you','girl'); //window love you cause you is a girl //foo.call(obj,'you','girl'); //window love you cause you is a girl
1.上述函数中this是定义在setTimeout定时器函数内部,所以this指向window,所以执行foo() this指向window.
2.call是指将foo函数中的this指向obj(即在obj对象内部环境执行foo函数),此时的foo函数的this并不是setTimeout函数内部的this
如想用到foo函数内部的this,可以先将this用一个变量保存起来,代码如下
function foo(name,sex){ var that = this; setTimeout(function(){ console.log(that.name+' love '+name+' cause '+name+' is a '+sex); },100); } foo('you','girl'); //window love you cause you is a girl foo.call(obj,'you','girl'); //I love you cause you is a girl foo.apply(obj,['you','girl']); //I love you cause you is a girl
当用ES6箭头函数时,内部的this始终是指向一开始创建的对象(函数)
function arrow_foo(name,sex){ setTimeout(() => { console.log(this.name+' love '+name+' cause '+name+' is a '+sex); },100); } arrow_foo('you','girl'); //window love you cause you is a girl arrow_foo.call(obj,'you','girl'); //I love you cause you is a girl
将上述ES6代码用谷歌转化工具traceur转换成ES5,原理就一目了然了:代码如下
function arrow_foo(name, sex) { var $__0 = this; setTimeout(function() { console.log($__0.name + ' love ' + name + ' cause ' + name + ' is a ' + sex); }, 100); }
一段代码总结call,apply,bind,$proxy
function arrow_foo(name,sex){ setTimeout(() => { console.log(this.name+' love '+name+' cause '+name+' is a '+sex); },100); } arrow_foo('you','girl'); //window love you cause you is a girl arrow_foo.call(obj,'you','girl'); //I love you cause you is a girl arrow_foo.bind(obj,'you','girl')();//I love you cause you is a girl $.proxy(arrow_foo,obj,'you','girl')();//I love you cause you is a girl
总结
由以上代码可以总结出:
1. foo.call()与foo.apply()原理是一样的,将foo函数的this指向指定的对象(或者表述为在指定对象的上下文环境中运行foo函数);
2. bind(obj)与$proxy(obj)不同的是他们返回的是一个新的函数,该函数的this执行指定的对象obj。