Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
702 views
in Technique[技术] by (71.8m points)

events - JavaScript Callback Scope


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

(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;  
  };  
} 

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...