关于javascript:我应该使用window.variable还是var?

Should I use window.variable or var?

我们有很多设置JS代码,用于定义将在许多其他JS文件中使用的面板,按钮等。

通常,我们会这样做:

grid.js

1
var myGrid = .....

combos.js

1
var myCombo = .....

然后,在我们的应用程序代码中,我们:

的application.js

1
2
3
function blah() {
    myGrid.someMethod()
}

someother.js

1
2
3
4
function foo() {
    myCombo.someMethod();
    myGrid.someMethod();
}

那么,我们应该使用var myGrid还是更好地使用window.myGrid

有什么不同?


功能上潜在的重要差异是window.myGrid可以delete d,var myGrid不能。

1
2
3
4
5
6
7
8
9
10
var test1 = 'value';
window.test2 = 'value';


console.log( delete window.test1 ); // false ( was not deleted )
console.log( delete window.test2 ); // true  ( was deleted )


console.log( test1 );  // 'value'         ( still accessible )
console.log( test2 );  // ReferenceError  ( no longer exists )


我建议创建一个名称空间变量var App = {};

1
App.myGrid = ...

这样你就可以限制全局命名空间的污染。

编辑:关于变量问题的数量 - 想到2个可能的解决方案:

  • 您可以通过类型(网格,按钮等)或关系(ClientInfoSection,AddressSection等)进一步命名它们。
  • 您将方法封装在使用您拥有的组件实例化的对象中
  • 例如:你有

    1
    2
    3
    4
    function foo() {
        myCombo.someMethod();
        myGrid.someMethod();
    }

    变为:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var Foo = function(combo, grid) {
        var myCombo = combo;//will be a private property
        this.myGrid = grid;//will be a public property
        this.foo = function() {//public method
            myCombo.someMethod();
            myGrid.someMethod();
        }
    }
    App.myFoo = new Foo(someCombo, someGrid);
    App.myFoo.foo();

    这样你就可以限制小对象的数量,只暴露你需要的东西(即foo函数)

    PS:如果需要公开内部组件,则将它们添加到构造函数内部


    window.variable的一个很好的用途是你可以检查它而不会出现javascript错误。例如,如果您有:

    1
    2
    3
    if (myVar) {
        //do work
    }

    并且myVar未在页面上的任何位置定义,您将收到javascript错误。然而:

    1
    2
    3
    if (window.myVar) {
        //do work
    }

    没有错误,并按照人们的预期工作。

    var myVar = 'test'window.myVar = 'test'大致相同。

    除此之外,正如其他人所说,你应该从一个全局对象下降,以避免污染全局命名空间。


    在全球范围内,这两者实际上是功能相同的。在函数范围中,当需要闭包的行为时,var当然是优选的。

    我会一直使用var:首先,它与闭包中通常首选的行为一致(因此,如果您决定稍后将代码移动到闭包中更容易),其次,它只是感觉更多对我说,我正在创建一个变量,而不是附加窗口的属性。但在这一点上它主要是风格。


    问题的一般答案是使用var

    更具体地说,始终将您的代码放在一个立即调用的函数表达式(IIFE)中:

    1
    2
    3
    4
    5
    (function(){
      var foo,
          bar;
      ...code...
    })();

    这使像foobar这样的变量不会污染全局命名空间。然后,当您明确希望变量位于全局对象(通常为window)上时,您可以编写:

    1
    window.foo = foo;

    JavaScript具有功能范围,充分利用它是非常好的。你不希望你的应用程序破解只是因为其他程序员做了一些愚蠢的事情,就像覆盖你的计时器句柄一样。


    除了其他答案之外,值得注意的是,如果在声明变量时不在函数内部使用var,它会自动泄漏到全局作用域,使其成为window对象(或全局作用域)的属性。


    为了扩展Liviu所说的内容,请使用:

    1
    2
    3
    4
    5
    App = (function() {
        var exports = {};
        /* code goes here, attach to exports to create Public API */
        return exports;
    })();

    通过这样做,您可以隐藏一些特定于实现的代码,您可能不希望通过使用var来暴露这些代码。但是,您可以访问附加到exports对象的任何内容。