从另一个属性的函数中使用时,对象文字根属性是未定义的

时间:2013-04-23 02:45:19

标签: javascript jquery object-literal

我已经读了几个小时,似乎无法找到适合我需要的答案。由于代码的大小,此时我不想更改结构。我试图找到一个解决方案,该解决方案可以在我已经实现的结构内工作,如果可能的话。

首先,这是一个非常简化的对象文字结构模型:

NS = 
{
    x: undefined,

    button: undefined,

    fn: 
    {
        root: undefined,

        doSomething: function () 
        {
            var root = this.root,
                x = root.x;       // exception occurs here

            // do something with x
        }
    },

    init: function () 
    {
        var self = this,
            x = self.x,
            button = self.button,
            fn = self.fn,
            fn.root = self;

        x = $("#x");
        button = $("#button");    

        button.on("click", fn.doSomething);
    }
};

我知道看起来init()下的声明并不是真的需要,但命名空间可能会变得很长,所以我喜欢这样缩短它们。在我遇到这个障碍之前,这几乎在每个场景中对我都很有用。我知道我可以完全限定所有内容并且它应该可以工作,但由于前面提到的长命名空间,我真的不想这样做。

我的问题是我的root属性x在从init()函数中设置后,在从另一个属性的函数中访问它时,它的值不会保留。您可以console.log(this.x)功能init()内的x = root.x。但是,当您单击该按钮并且onClick函数尝试声明它将抛出console.log()时:

  

未捕获的TypeError:无法读取未定义的属性“x”


更新

添加fn.root.x表明即使在调用处理程序之前init: function () { var self = this, x = self.x, button = self.button, fn = self.fn, fn.root = self; x = $("#x"); console.log(x); // this shows the object console.log(fn.root.x); // this throws the undefined exception button = $("#button"); button.on("click", fn.doSomething); } 未定义:

{{1}}

2 个答案:

答案 0 :(得分:3)

当doSomething被称为事件处理程序时,this将成为函数内的事件目标。所以this.root将是未定义的,未定义的没有任何属性,因此root.x会引发错误。

一种解决方案是使用$.proxy修复this的值:

button.on("click", $.proxy(fn.doSomething, self));

答案 1 :(得分:0)

实际上,JS对象和数组是通过引用传递的。在您的示例中,如果x是对象而不是undefined

NS = {
    x: {},
    button: undefined,
    // etc
};

然后在你的init方法中你可以做这样的事情,它会起作用:

init: function(){
    var self = this,
        x = self.x;

    x.foo = 'foo!';
    console.log(self.x.foo);  // Logs 'foo!'
}

但是,在您的示例中,当您指定x = $('#x')时,实际上只是将此本地x变量的引用更改为新创建的jQuery对象。您的示例需要做的是使两个变量引用相同的对象:

init: function(){
    var self = this,
        x = self.x = $('#x');

    x.on('click', function(){
        console.log('foo!');
    });

    self.x.trigger('click');  // Logs 'foo!'
}
相关问题