JavaScript回调范围 [英] JavaScript Callback Scope

查看:87
本文介绍了JavaScript回调范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 我在一个回调函数中引用了我的对象, function foo(id){
this.dom = document.getElementById(id);
this.bar = 5;
var self = this;
this.dom.addEventListener(click,self.onclick,false);
}

foo.prototype = {
onclick:function(){
this.bar = 7;
}
};

现在,当我创建一个新对象时(DOM加载后,使用span#test) / p>

  var x = new foo('test'); 

onclick函数中的this指向span#test而不是foo对象。 / p>

如何在onclick函数中获取对foo对象的引用?

解决方案



问题出现在下面一行:

  this.dom.addEventListener(click,self.onclick,false); 

这里,传递一个函数对象用作回调。当事件触发时,函数被调用,但现在它与任何对象(this)没有关联。



问题可以通过包装函数参考),如下所示:

  this.dom.addEventListener(
click,
function(event){self.onclick(event)},
false);

由于变量self在创建闭包时被赋予



解决这个问题的另一种方法是创建一个效用函数(避免使用变量)绑定 ):

 函数绑定(scope,fn){
return function (){
fn.apply(scope,arguments);
};
}

更新的代码将如下所示:

  this.dom.addEventListener(click,bind(this,this.onclick),false); 






Function.prototype.bind 是ECMAScript的一部分5并提供相同的功能。所以你可以这样做:

  this.dom.addEventListener(click,this.onclick.bind(this),false) ; 

对于不支持ES5的浏览器, MDN提供以下填充

  if(!Function.prototype.bind){
Function.prototype.bind = function(oThis){
if(typeof this!==function){
//最近可能的ECMAScript 5内部IsCallable函数
throw new TypeError(Function.prototype.bind - 试图绑定的是不可调用的);
}

var aArgs = Array.prototype.slice.call(arguments,1),
fToBind = this,
fNOP = function(){},
fBound = function(){
return fToBind.apply(this instanceof fNOP
?this
:oThis || window,
aArgs.concat(Array.prototype.slice .call(arguments)));
};

fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();

return fBound;
};
}


I'm having some trouble with plain old JavaScript (no frameworks) in referencing my object in a callback function.

function foo(id) {
    this.dom = document.getElementById(id);
    this.bar = 5;
    var self = this;
    this.dom.addEventListener("click", self.onclick, false);
}

foo.prototype = {
    onclick : function() {
        this.bar = 7;
    }
};

Now when I create a new object (after the DOM has loaded, with a span#test)

var x = new foo('test');

The 'this' inside the onclick function points to the span#test and not the foo object.

How do I get a reference to my foo object inside the onclick function?

解决方案

(extracted some explanation that was hidden in comments in other answer)

The problem lies in the following line:

this.dom.addEventListener("click", self.onclick, false);

Here, you pass a function object to be used as callback. When the event trigger, the function is called but now it has no association with any object (this).

The problem can be solved by wrapping the function (with it's object reference) in a closure as follows:

this.dom.addEventListener(
  "click",
  function(event) {self.onclick(event)},
  false);

Since the variable self was assigned this when the closure was created, the closure function will remember the value of the self variable when it's called at a later time.

An alternative way to solve this is to make an utility function (and avoid using variables for binding this):

function bind(scope, fn) {
    return function () {
        fn.apply(scope, arguments);
    };
}

The updated code would then look like:

this.dom.addEventListener("click", bind(this, this.onclick), false);


Function.prototype.bind is part of ECMAScript 5 and provides the same functionality. So you can do:

this.dom.addEventListener("click", this.onclick.bind(this), false);

For browsers which do not support ES5 yet, MDN provides the following shim:

if (!Function.prototype.bind) {  
  Function.prototype.bind = function (oThis) {  
    if (typeof this !== "function") {  
      // closest thing possible to the ECMAScript 5 internal IsCallable function  
      throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");  
    }  

    var aArgs = Array.prototype.slice.call(arguments, 1),   
        fToBind = this,   
        fNOP = function () {},  
        fBound = function () {  
          return fToBind.apply(this instanceof fNOP  
                                 ? this  
                                 : oThis || window,  
                               aArgs.concat(Array.prototype.slice.call(arguments)));  
        };  

    fNOP.prototype = this.prototype;  
    fBound.prototype = new fNOP();  

    return fBound;  
  };  
} 

这篇关于JavaScript回调范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆