我应该使用 window.variable 还是 var?

IT技术 javascript global-variables
2021-03-13 19:13:56

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

通常,我们会执行以下操作:

网格.js

var myGrid = .....

组合.js

var myCombo = .....

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

应用程序.js

function blah() {
    myGrid.someMethod()
}

其他人.js

function foo() {
    myCombo.someMethod();
    myGrid.someMethod();
}

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

有什么不同?

6个回答

功能上一个潜在的重要差异是window.myGrid可以deletevar myGrid不能。

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 )
这是最佳答案,因为它实际上回答了问题。
2021-04-22 19:13:56
"var" 似乎使用 configure=false 调用 Object.defineProperty
2021-04-27 19:13:56
在属性描述符中,configurable:false是唯一的区别。请参阅 ( jsbin.com/zazuzi/edit?js,console ) 现在,为什么会有这种差异?它似乎在这里得到了回答(developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...),它说delete is only effective on an object's properties. It has no effect on variable or function names.全局变量确实驻留在全局对象上的事实是一个“实现”细节,但是声明变量的意图和特征是通过可配置标志保留的。
2021-04-27 19:13:56

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

App.myGrid = ...

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

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

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

例如:你有

function foo() {
    myCombo.someMethod();
    myGrid.someMethod();
}

变成:

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:如果需要暴露内部组件,则在构造函数中将它们添加到 this 中

我喜欢这个主意。但是,如果我们little objectsApp全局中拥有数百甚至数千个类似按钮、数字字段等,它仍然实用吗?
2021-05-01 19:13:56
@cbmeeks - 如果您有数千个(命名)对象,那么将它们声明为某些主对象(例如App. 如果您不这样做,那么您就是将那数千个名称添加到“窗口”中——这将不再实用——它们总是附加到某些东西上
2021-05-10 19:13:56
@cbmeeks 没有人阻止你进一步命名你的变量 App.Grids.myGrid 等
2021-05-17 19:13:56
+1 这就是我的答案。这也有一个好处,即创建一个唯一的名称,可以将您的应用程序与其他人的应用程序区分开来。
2021-05-20 19:13:56
所以......明确地说(四年后),你的答案是var所有这些关于命名空间的业务都与问题无关。命名空间本身仍然是一个全局变量,必须使用一种或另一种方法创建。
2021-05-20 19:13:56

一个很好的用途window.variable是您可以在没有 javascript 错误的情况下检查它。例如,如果您有:

if (myVar) {
    //do work
}

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

if (window.myVar) {
    //do work
}

没有错误,并且按预期工作。

var myVar = 'test'并且window.myVar = 'test'大致相等。

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

值得一提的是,使用MyApp.myVar(请参阅已接受的答案)与window.myVar(只要MyApp已在某处声明)具有相同的好处var App = {};... App.myVar = "whatever";... if (App.myVar) ...... if (App.thisVarWasNeverDeclared) {...}- 没有错误,只是跳过该代码。为了测试,如果从未声明:if (App.myVar === undefined) { App.myVar = "some default"; }
2021-05-11 19:13:56

在全局范围内,两者实际上在功能方面是等效的。在函数范围内,var当需要闭包的行为时当然更可取。

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

它们并不完全相同。的属性window可以使用delete运算符删除,而使用声明的变量var不能删除。此外,仅使用的代码var可移植到非浏览器环境。
2021-04-30 19:13:56
蒂姆:即使在全球范围内?这个工作对我来说(在Chrome中,至少)var x = 10; delete window.x;后一个语句返回true,当我之后尝试引用时x,我得到一个ReferenceError. 不过,我还没有阅读规范,所以 V8 可能不符合这种方式。
2021-05-01 19:13:56
所以我是。我站得更正;我应该更加小心地在 JavaScript 控制台中验证这样的边缘情况
2021-05-02 19:13:56
@Tim Down +1 提醒我并非所有 JS 都会在客户端运行。
2021-05-06 19:13:56

这个问题的一般答案是使用var.

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

(function(){
  var foo,
      bar;
  ...code...
})();

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

window.foo = foo;

JavaScript 具有功能范围,充分利用它真的很好。你不希望你的应用程序因为其他程序员做了一些愚蠢的事情而崩溃,比如覆盖了你的计时器句柄。