开发者

This pointer from internal function

i have JavaScript components, that has following architecture:

var MyComponent = function(params)
{
    setup(params);


    this.doSomething()
    {
        // doing something
    };

    function setup(params)
    {
        // Setup

        // Interaction logic
        var _this = this; // "this" points to DOMWindow, not to created object
        $(".some-element").click(function(){
            _this.doSomething(); // it craches here, because of above
        });
    }
};

When something, being controlled by interaction logic, happens, sometimes i must forward execution to "public" methods of component.

In this situation, i have a problem with "this" pointer.

Sample code demonstrates it:

var Item = function()
{
    this.say = function()
    {
        alert("hello");
    };
    this.sayInternal = function()
    {
        _sayInternal();
    };
    function _sayInternal()
    {
        this.say();
    };
};

To test it,

  • Create an object:

var o = new Item();

  • This works fine:

o.say(); // alerts "hello"

  • This crashes:

o.sayInterna开发者_JAVA百科l();

I get an error:

TypeError: Result of expression 'this.say' [undefined] is not a function.

I think, such a behaviour takes place, because _sayInternal() function is declared (and not assigned to object, like "this.say = function()"). This way, it is shared across all created objects and acts like a static function in C++.

Is this true ?


No, sayInternal is not shared between created objects. But you are right, the created objects don't have access to sayInternal as it is not assigned to them. This function is only local to the constructor function.

this always refers to the context a function is invoked in. If you call it like func(), then this refers to the global object (which is window in browser). If you set the function as property of an object and call it with obj.func(), then this will refer to obj.

If you assign a "bound" function to a variable and call it:

var method = obj.func;
method();

then this will again refer to the global object. In JavaScript, functions are like any other value, they don't have a special relationship to the object they are assigned to.


You can explicitly set the context with call or apply:

var MyComponent = function(params)
{
    setup.call(this, params); // <- using `call`

    this.doSomething()
    {
        // doing something
    };

    function setup(params)
    {
        // Setup  
        // Interaction logic
        var _this = this; // "this" to new  created object
        $(".some-element").click(function(){
            _this.doSomething();
        });
    }
};

or in you other example:

var Item = function()
{
    this.say = function()
    {
        alert("hello");
    };
    this.sayInternal = function()
    {
        _sayInternal.call(this);
    };
    function _sayInternal()
    {
        this.say();
    };
};

That said, this approach to assign functions to objects is not good, because every instance will have its own this.sayInternal function. So for the Item code above, every creation of an instance involves creating three functions too, which is a waste of memory.

Making use of prototype inheritance would be a better way:

var Item = function() {
};

Item.prototype = (function() {
    function _sayInternal() {
        this.say();
    };

    return {
        say: function() {
            alert("hello");
        },
        sayInternal: function(){
            _sayInternal.call(this);
        }
    }
}());

This way, _sayInternal is only created once and all instances inherit (refer to) the prototype, so say and sayInternal also exist only once. The "trick" with the immediate function makes _sayInternal only accessible by say and sayInternal.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜