欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

Registering JavaScript object methods as cal

系統 2737 0

Registering JavaScript object methods as callbacks

The registration of callback functions is very common in JavaScript web programming, for example to attach user interface event handlers (such as onclick), or to provide a function to handle an XHR response. Registering an object method as a callback function is not entirely straightforward, but there are a number of approaches that we can use.

Let's say we've got a constructor, an object, and a function that registers a callback:

          
            function MyObject(val){
    this.val = val;
}
MyObject.prototype.alertVal = function(){
    alert(this.val);
}

var obj = new MyObject(8);

function register(callback){
    // some time later...
    callback();
}

          
        

The constructor stores its single argument, and the alertVal() method alerts it. The simple register() function takes a function and calls it. In a real situation the behaviour here would be much more interesting but this will do for illustration.

Why we don't want to just pass obj.alertVal to register()

Object methods are first-class functions in JavaScript and we could pass obj.alertVal to register() -- but it isn't quite what we want. Let's see what happens:

          
            register(obj.alertVal);
// inside register(), callback === obj.alertVal
callback()
// inside MyObject.prototype.alertVal
alert(this.val);
// because callback() was not called on an object,
// this === the JavaScript global object and not obj;
// this.val is the global variable val, not obj.val

          
        

When a function is called as a method on an object (obj.alertVal()), "this" is bound to the object that it is called on (obj). And when a function is called without an object (func()), "this" is bound to the JavaScript global object (window in web browsers.) When we passed obj.alertVal to register() we were passing a reference to the function bound to obj.alertVal, but no reference to the object obj.

So, we need to bind our method to the object.

Closure with an anonymous function

In JavaScript, whenever a function is defined within another one a closure is created [ JavaScript Closures for Dummies ] [ JavaScript Closures ]. A closure remembers the variable bindings that were in scope when the function was created. These bindings are then available whenever the function is called. We can bind our method to our object instance with the following:

          
            register(function(){obj.alertVal()});

          
        

Whenever the anonymous function is called, "obj" will be bound to the value that it had when the function was created. Which is exactly what we want.

(If we execute the above code outside a function it will behave differently. No closure will be created, instead, the current value of the global variable "obj" will be used whenever the anonymous function is called, not the value at function definition.)

If we want to register a method on the object currently bound to "this", we need to take an extra step:

          
            var obj = this;
register(function(){obj.alertVal()});

          
        

If we don't explicitly bind "this" to a named variable (obj) and instead use register(function(){this.alertVal()}) we will lose our object reference. "this" will be bound to the JavaScript global object whenever the anonymous function is called.

Build a generic closure maker

Instead of building a closure each time we want to register a method as a callback, we could write a utility function to do it for us. For example:

          
            function bind(toObject, methodName){
    return function(){toObject[methodName]()}
}

          
        

With such a function we can then register our method with:

          
            register(bind(obj, "alertVal"));

          
        

Dojo (dojo.hitch()) and Prototype ( bind() ) both have such utility functions (that also allow you to provide arguments to pass to the method when called, something that our "bind" doesn't do.)

If we want to register a method of "this", we don't need to explicitly bind it (as we did above) before calling "bind" -- the function call does the binding for us. register(bind(this, "alertVal")) works as expected.

Alter the register function to take the object too

If we changed our register function to:

          
            function register(anObject, methodName){
    // some time later...
    anObject[methodName]();
}

          
        

We could register our call with:

          
            register(obj, "alertVal");

          
        

dojo.connect and YUI's YAHOO.util.Event.addListener() [ YUI Event Utility ] [ YAHOO.util.Event API docs ] both include this binding style in their API.

Bind the method to the object at construction

We could bind our method to the object (or instance variables as shown here) in the constructor function:

          
            function MyObject(val){
    this.alertVal = function(){
        alert(val);
    }
}

          
        

We could then register obj.alertVal directly as "val" is already bound:

          
            obj = new MyObject(8);
register(obj.alertVal);

          
        

Douglas Crockford writes about this programming style in Private Members in JavaScript.

Circular references and memory leaks

Whichever method you use you need to be careful about avoiding circular references when registering event handlers (such as onclick) on document objects. For example, if we register an object method as an event handler on an element, such that the method is bound to the object, and the object has a reference back to the element, then we have a circular reference, and a potential leak (in this case a solution would be to have the object store the element's id rather than store a reference to the element object itself.) Here are some articles that discuss ways to cause memory leaks and ways to avoid them:

About me

Simon Bates is a software developer living and working in Toronto.

Starting points

Colophon

This blog is running on a Python application that I built with Django . The source code is available under the MIT license.

Registering JavaScript object methods as callbacks(注冊一個對像方法為回調函數[解決回調函數的上下文問題])


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 91高清在线观看 | 日本精品久久 | 亚洲欧美在线视频 | 狠狠操夜夜操 | 亚洲第五色综合网 | 91资源在线观看 | 日韩亚洲视频 | 福利免费在线 | 亚洲综合在线另类色区奇米 | 加勒比综合 | 狠狠狠狠狠狠狠狠狠狠 | 亚洲精品一区在线 | 国产精品玖玖玖在线观看 | 国产色婷婷视频在线观看 | 免费激情网址 | 成人免费网站视频 | 香蕉久久一区二区不卡无毒影院 | 色悠久久久久综合网伊人男男 | 久久精品免费一区二区三 | 99亚洲精品 | 国产一卡2卡三卡4卡免费网站 | 国产va免费精品观看精品 | 精品一区二区三区视频 | 天天操夜夜爽 | 国产日韩精品一区 | 99视频在线观看精品 | 亚洲区国产区 | 色综合网亚洲精品久久久 | 日日插夜夜操 | 奶子吧naiziba.cc免费午夜片在线观看 | 欧美18videos极品 | 精品小视频在线观看 | 国产专区在线视频 | 毛片免费观看 | 亚洲 欧美 另类 综合 偷拍 | 一级黄色片欧美 | 影音先锋资源av | 成人一区二区三区在线 | 色无极在线 | 91视频在线 | 手机在线观看你懂得 |