这个指针来自内部函数

时间:2011-02-15 10:09:41

标签: javascript scope

我有JavaScript组件,具有以下架构:

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

当由交互逻辑控制的事情发生时,有时我必须将执行转发给组件的“公共”方法。

在这种情况下,我对“this”指针有疑问。

示例代码演示了它:

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

要测试它,

  • 创建一个对象:

var o = new Item();

  • 这很好用:

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

  • 这次崩溃:

o.sayInternal();

我收到错误:

  

TypeError:表达式'this.say'[undefined]的结果不是函数。

我认为,这样的行为发生了,因为_sayInternal()函数是声明(并没有分配给对象,比如“this.say = function()”)。这样,它在所有创建的对象之间共享,并且像C ++中的静态函数一样。

这是真的吗?

1 个答案:

答案 0 :(得分:3)

不,sayInternal不在创建的对象之间共享。但是你是对的,创建的对象无法访问sayInternal,因为它没有分配给它们。此函数仅对构造函数本地。

this始终引用调用函数的上下文。如果您将其称为func(),则this引用全局对象(window in浏览器)。如果您将该函数设置为对象的属性并使用obj.func()进行调用,则this将引用obj

如果为变量分配“绑定”函数并调用它:

var method = obj.func;
method();

然后this将再次引用全局对象。在JavaScript中,函数与任何其他值一样,它们与分配给它们的对象没有特殊的关系。


您可以使用callapply

明确设置上下文
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();
        });
    }
};

或在你的其他例子中:

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

也就是说,这种向对象分配函数的方法并不好,因为每个实例都有自己的this.sayInternal函数。因此,对于上面的Item代码,每个实例的创建都涉及创建三个函数,这会浪费内存。

使用prototype inheritance会更好:

var Item = function() {
};

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

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

这样,_sayInternal只创建一次并且所有实例都继承(引用)原型,因此saysayInternal也只存在一次。使用立即功能的“技巧”只能_sayInternalsay访问sayInternal