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

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

4

4 回答 4

4

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

var foo = '123';

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

哪个更方便,一目了然。在某些情况下,使用窗户是有意义的,但这种情况几乎总是因为糟糕的建筑。使用 window 允许我们访问一个变量全局变量 - 有趣的措辞 :) 这应该清除它:

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

这种事情在对象中很常见,但在窗口中却没有。原因是我们应该尽可能避免全局变量(窗口的属性)。因此,任何需要变量属性名称的逻辑都应该在对象内部,处理对象 - NOT 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被调用的属性steve,它是一个函数。我将使用 IIFE(立即调用的函数表达式),而不是steve直接创建为函数,它是一个函数,return可以设置为steve.
在 IIFE 中,我将为它创建函数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是一个复杂的函数并且您想将其分解为其他一些只有steve自己知道的小函数,这将非常有用。

于 2013-11-14T22:18:02.000 回答
1

如果您声明使用var它不会与全局window范围相关联。相反,它是一个局部变量。bob 也不是 steve 对象的属性,他们设置它的方式

于 2013-11-14T22:18:00.267 回答
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;
    })();
于 2013-11-14T22:20:34.320 回答
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"];
于 2013-11-14T22:23:41.720 回答