如何访问从函数创建和返回的对象的属性

时间:2013-11-14 22:15:15

标签: javascript

var steve = function() {
  var bob = {};
  bob.WayCoolTest = function () {console.log('done deal');};
  return bob;
}
window["steve"]["WayCoolTest"]

在我的测试应用程序的chrome控制台中运行它,任何地方的结果都是未定义的。我不明白为什么,有人可以解释为什么这不起作用并帮助我解决它。非常感谢!!

4 个答案:

答案 0 :(得分:4)

使用窗口通常是多余的 - 让我演示一下:

var foo = '123';

alert(foo); //123
alert(window.foo) //123
alert(window['foo']) //123

很明显哪个更方便。在某种情况下,使用窗口是有意义的,但这种情况几乎总是因为糟糕的架构。使用窗口允许我们访问变量全局变量 - 有趣的措辞:)这应该清除它:

var foo = '123';
var bar = 'abc';

var prop;
if (blah) { //some condition here
  prop = 'foo';
}
else {
  prop = 'bar';
}

现在......我们如何使用prop来获取相应变量的值?

console.log(window[prop]); //123 or abc - bracket notation lets us use variable property names

这种事物在对象中非常常见,但不适用于窗口。原因是我们应该尽可能地避免全局变量(窗口的属性)。因此,任何需要变量属性名称的逻辑都应该在对象内部,处理对象 - 不是window。现在窗口可能不合适了。

在其他功能中创建功能通常是不好的做法。这意味着每次调用函数A时,都会重新创建函数B.大多数情况下,人们这样做是因为他们不知道更好,而不是因为他们需要。

在我看来,您打算给steve一个名为WayCoolTest的属性,这两个属性都是函数。这可以做到。

var steve = function() {
  console.log("I'm Steve!");
}
steve.WayCoolTest = function() {
  console.log("I'm a Way Cool Test!");
}

steve(); //I'm Steve!
steve.WayCoolTest(); //I'm a Way Cool Test!

这是有效的,因为函数是javascript中的对象。因此,您可以向它们添加属性。

让我们加快步伐吧!
为了强调良好实践,我将把这个例子包装在一个对象testApp中(它就像一个名称空间......我们使用它而不是窗口)。
我将创建一个名为testApp的{​​{1}}属性,它将是一个函数。 我不会直接创建steve作为函数,而是使用IIFE(立即调用的函数表达式),这是一个将steve设置为return的函数。
在IIFE中,我将为steve创建函数并附加steve,如前面的示例所示,然后返回该函数并将其分配给WayCoolTest

steve

现在,让我们考虑另一种变体。

var testApp = {
  steve : (function() {
    var steve = function() { //the name here doesn't matter, just being consistent, since this will be the value of the property `steve`.
      console.log("I'm Steve!");
    }
    steve.WayCoolTest = function() {
      console.log("I'm a Way Cool Test!");
    }
    return steve;
  }());
};

testApp.steve(); //I'm Steve;
testApp.steve.WayCoolTest(); //I'm a Way Cool Test!

如果例如var testApp = { steve : (function() { var steve = function() { //the name here doesn't matter, just being consistent, since this will be the value of the property `steve`. console.log("I'm Steve!"); WayCoolTest(); //Steve can use this, but nothing else can! Encapsulation. } var WayCoolTest = function() { //THIS PART!! No longer a property of "steve" console.log("I'm a Way Cool Test!"); } return steve; }()); }; testApp.steve(); //I'm Steve! I'm a Way Cool Test testApp.steve.WayCoolTest(); //undefined, of course 是一个复杂的函数,并且您希望将其分解为只有steve知道的其他一些小函数,那么这非常有用。

答案 1 :(得分:1)

如果您声明使用var,则它不会与全局window范围相关联。它是一个局部变量。另外bob不是你设置的史蒂夫对象的属性

答案 2 :(得分:1)

假设steve在全局范围内并且您似乎不使用steve作为构造函数,则可以使用立即函数并返回您在其中创建的新对象。

var steve = (function () {
    var bob = {};
    bob.WayCoolTest = function () {
        console.log('done deal');
    };
    return bob;
})();

window["steve"]["WayCoolTest"]();

如果它在一个闭包中,那么你必须删除var才能使其成为窗口的一部分,或者将它作为一个属性设置为窗口对象。

  window.steve = (function () {
        var bob = {};
        bob.WayCoolTest = function () {
            console.log('done deal');
        };
        return bob;
    })();

答案 3 :(得分:1)

为了补充其他答案,您的代码将以这种方式工作:

var steve = function() {
    var bob = {};
    bob.WayCoolTest = function () {console.log('done deal');};
    return bob;
}
window["steve"]()["WayCoolTest"]();

var steve = (function() {
    var bob = {};
    bob.WayCoolTest = function () {console.log('done deal');};
    return bob;
})();
window["steve"]["WayCoolTest"]();

或者,最脏的方式......

steve=(function() {
    var bob = {};
    bob.__defineGetter__("WayCoolTest", function () {console.log('done deal');});
    return bob;
})();
window["steve"]["WayCoolTest"];