标签:类 javascript 早绑定 晚绑定 function
javaScript会在调用时会设置执行上下文“this”的值。
我们举一个例子,给一个Menu构造函数,来接受一个元素来创建一个菜单。
function Menu(elem){ //... } //使用 var elem = document.getElementById(‘something‘) // a DOM element var menu = new Menu(elem);
当我们在构造函数里调用setTimeout时,你也许想引用这个menu对象,我们可能会像如下这样做:
function Menu(elem){
setTimeout(function(){
alert(this); //window, not menu!
}, 1000);
}
new Menu(document.createElement(‘div‘));
但是this指向的是window,因为setTimeout总是在window上下文环境中执行,再看下面的例子:
function Menu(elem){
elem.onclick = function(){
alert(this); //elem, not menu!
}
}
元素事件处理器将this设置为指向elem而不是menu。私有方法或本地函数:本地函数经常被用来作为私有方法。
function Menu(elem){
function privateMethod(){
alert(this); //window,not menu!
}
//调用私有方法
privateMethod();
}
new Menu(document.createElement(‘div‘));
调用私有方法,this也是指向window。
首先,我们可以在闭包中存储this。
下面的例子中,将this赋值给self,用self来代替this的使用。
function Menu(elem){
var self = this;
setTimeout(function(){
alert(self); //object, menu!
}, 1000);
}
new Menu(document.createElement(‘div‘));
我们需要用到一个帮助函数bind来强制绑定到this。
function bind(func, fixThis){
return function(){
return func.apply(fixThis, arguments);
}
}
function Menu(elem){
elem.onclick = bind(function(){
alert(this); //object!(menu)
},this);
}
Function.prototype.bind = Function.prototype.bind || function(fixThis){ var func = this; return function(){ return func.apply(fixThis, arguments); } }
可能有些人觉得这样做污染了原生的属性,不推荐这种用法。但是改变Function.prototype有时也是能够接受的。它不会影响对象或数组的迭代,副作用非常小的。
如果用上面这种方法,那会简单很多。
setTimeout
function Menu(elem) {
setTimeout(function() {
alert(this) // object! (menu)
}.bind(this), 1000)
}
new Menu(document.createElement(‘div‘))
onclick
function Menu(elem) {
elem.onclick = function() {
alert(this) // object! (menu)
}.bind(this)
}
私有方法或本地方法
但是有点问题,在函数声明时不能调用bind,在函数表达式时是可以的。
function Menu(elem) { function privateMethod() { alert(this); }.bind(this); // syntax error, can‘t call method in-place } function Menu(elem) { var privateMethod = function() { alert(this); }.bind(this); privateMethod(); } new Menu(document.createElement(‘div‘));
迟绑定的意思就是在调用时进行绑定,而早绑定是及时绑定,也就是在函数声明时就已经确定好了。
早绑定的问题
以下例子我们点击body后我们发现输出的不是"SuperMenu",而是"Menu"。
<!DOCTYLE HTML> <html> <body> <script> function bind(func, fixThis) { return function() { return func.apply(fixThis, arguments); } } function Menu(elem) { this.sayHi = function() { alert(‘Menu‘); } elem.onclick = bind(this.sayHi, this); } function SuperMenu(elem) { Menu.apply(this, arguments); this.sayHi = function() { alert(‘SuperMenu‘); } } new SuperMenu(document.body); </script> </body> </html>
真正的晚绑定
这次我们看到了我们想要的结果,输出的是“SuperMenu"。关键一步是:fixThis[funcName]是动态从去获取对象的属性,当运行时改变该属性时也能正确执行调用。其实如果你目前用的是jquery库的话,$.proxy已经实现了早绑定和迟绑定,具体可以查看相关API。
<!DOCTYLE HTML> <html> <body> <script> function bindLate(funcName, fixThis) { return function() { return fixThis[funcName].apply(fixThis, arguments); } } function Menu(elem) { this.sayHi = function() { alert(‘Menu‘); } elem.onclick = bindLate(this.sayHi, this); } function SuperMenu(elem) { Menu.apply(this, arguments) this.sayHi = function() { alert(‘SuperMenu‘); } } new SuperMenu(document.body); </script> </body> </html>
【javaScript】早绑定和迟绑定,码迷,mamicode.com
标签:类 javascript 早绑定 晚绑定 function
原文地址:http://blog.csdn.net/xiongjunlbs/article/details/24784255