Javascript 声明没有 var 关键字的变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6888570/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 23:38:00  来源:igfitidea点击:

Declaring variables without var keyword

javascriptvariablesglobal-variablesdeclaration

提问by xralf

At w3schools there is written:

在 w3schools 有写:

If you declare a variable, without using "var", the variable always becomes GLOBAL.

如果您声明一个变量,而不使用“var”,则该变量始终变为 GLOBAL。

Is it useful to declare global variable inside the function? I can imagine to declare some global variables in some event handler, but what is it good for? Better usage of RAM?

在函数内部声明全局变量有用吗?我可以想象在某个事件处理程序中声明一些全局变量,但它有什么用呢?更好地使用内存?

回答by T.J. Crowder

No, there's no RAM benefit or anything like that.

不,没有 RAM 好处或类似的东西。

What w3schools is talking about is something I call The Horror of Implicit Globals. Consider this function:

w3schools 谈论的是我称之为隐式全局变量的恐怖。考虑这个函数:

function foo() {
    var variable1, variable2;

    variable1 = 5;
    varaible2 = 6;
    return variable1 + variable2;
}

Seems simple enough, but it returns NaN, not 11, because of the typo on the varaible2 = 6;line. And it creates a global variable with the typo'd name:

看起来很简单,但它返回的是NaN,而不是11,因为行上有错字varaible2 = 6;。它创建了一个带有拼写名称的全局变量:

function foo() {
    var variable1, variable2;

    variable1 = 5;
    varaible2 = 6;
    return variable1 + variable2;
}
console.log(foo());     // NaN
console.log(varaible2); // 6?!?!?!

This is because the function assigns to varaible2(note the typo), but varaible2isn't declared anywhere. Through the mechanics of the scope chain in JavaScript, this ends up being an implicit assignment to a (new) property on the global object(which you can access as windowon browsers).

这是因为该函数分配给varaible2(注意错字),但未varaible2在任何地方声明。通过 JavaScript 中作用域链的机制,这最终是对全局对象(您可以window在浏览器上访问)上的(新)属性的隐式分配。

That's just a "feature" of loose-mode JavaScript, assigning to a completely undeclared identifier isn't an error; instead, it creates a propertly on the global object, and properties on the global object are global variables. (Up through ES5, all globals were properties of the global object. As of ES2015, though, a new kind of global was added that isn't a property of the global object. Global-scope let, const, and classcreate the new kind of global.)

这只是松散模式 JavaScript 的一个“特性”,分配给一个完全未声明的标识符不是错误;相反,它在全局对象上创建一个属性,全局对象上的属性是全局变量。(最多通过ES5,所有全局是全局对象。由于ES2015的,虽然加入了一种新的全球性不是全局对象的属性。全球范围的特性letconst以及class创建新的全球.)

My example is a typo, but of course, you could do it on purpose if you wanted. It's a clearly-defined part of the language, after all. So:

我的例子是一个错字,但当然,如果你愿意,你可以故意这样做。毕竟,它是语言的一个明确定义的部分。所以:

myNewGlobal = 42;

...anywhere that myNewGlobalisn't declared will create the new global.

...任何myNewGlobal未声明的地方都将创建新的全局。

But I would strongly recommend never doing it in purpose: It makes the code hard to read and maintain, and that code will be incompatible with JavaScript modules when they become more common and widespread. If you really need to create a global variable from within a function at runtime (already a red flag, but there are valid reasons for it), do it explicitly by assigning to a property on window(or whatever refers to the global object in your environment; it's windowon browsers):

但我强烈建议永远不要故意这样做:它使代码难以阅读和维护,并且当 JavaScript 模块变得更加普遍和广泛时,这些代码将与 JavaScript 模块不兼容。如果您确实需要在运行时从函数内部创建全局变量(已经是一个危险信号,但有正当理由),请通过分配给 on window(或任何引用您环境中的全局对象的属性)来显式执行; 它window在浏览器上):

window.myNewGlobal = 42;

In fact, I'd suggest using ES5's strict mode. Strict mode makes assigning to an undeclared identifier an error rather than silently creating a global. If we'd been using strict mode, the problem with fooabove would have been much easier to diagnose:

事实上,我建议使用 ES5 的严格模式。严格模式使分配给未声明的标识符成为错误,而不是默默地创建全局。如果我们一直使用严格模式,foo上面的问题会更容易诊断:

"use strict"; // Turns on strict mode for this compilation unit

function foo() {
    var variable1, variable2;

    variable1 = 5;
    varaible2 = 6;                 // <=== ReferenceError
    return variable1 + variable2;
}
console.log(foo());



Somewhat tangential, but in general I'd recommend avoiding globals wherever possible. The global namespace is already very, very cluttered on browsers. The browser creates a global for every element in the DOM with an id, for most elements with a name, and has several predefined globals of its own (like title) which can easily conflict with your code.

有点切线,但总的来说,我建议尽可能避免全局变量。全局命名空间在浏览器上已经非常非常混乱了。浏览器使用 为 DOM 中的每个元素创建一个全局变量id,对于大多数带有 的元素name,并且有几个自己的预定义全局变量(如title),它们很容易与您的代码发生冲突。

Instead, just define yourself a nice scoping function and put your symbols in it:

相反,只需为自己定义一个很好的作用域函数并将您的符号放入其中:

(function() {
    var your, symbols, here, if_they_need, to_be_shared, amongst_functions;

    function doSomething() {
    }

    function doSomethingElse() {
    }
})();

And if you do that, you might want to enable strict mode:

如果你这样做,你可能想要启用严格模式:

(function() {
    "use strict";
    var your, symbols, here, if_they_need, to_be_shared, amongst_functions;

    function doSomething() {
    }

    function doSomethingElse() {
    }
})();

...which, as mentioned, has the advantage of turning assignments to undeclared identifiers into errors (along with various other helpful things).

...正如前面提到的,它的优点是将未声明的标识符的赋值转化为错误(以及其他各种有用的东西)。

Note that in a JvaScript module(added in ES2015, but only now beginning to find their way into the wild), strict mode is enabled by default. (This is also the case with classdefinitions, also new in ES2015.)

请注意,在 JvaScript模块中(在 ES2015 中添加,但现在才开始找到它们的方式),默认情况下启用严格模式。(这也是class定义的情况,也是 ES2015 中的新内容。)

回答by user278064

Side Effects When Forgetting var

忘记 var 时的副作用

There's one slight difference between implied globals and explicitly defined ones. The difference is in the ability to undefine these variables using the delete operator:

隐含的全局变量和明确定义的全局变量之间有一个细微的区别。不同之处在于可以使用 delete 运算符取消定义这些变量:

? Globals created with var (those created in the program outside of any function) cannot be deleted.

? 不能删除用 var 创建的全局变量(在任何函数之外的程序中创建的那些)。

? Implied globals created without var (regardless if created inside functions) can be deleted.

? 可以删除没有 var 创建的隐式全局变量(无论是否在函数内部创建)。

This shows that implied globals are technically not real variables, but they are properties of the global object. Properties can be deleted with the delete operator whereas variables cannot:

这表明隐含的全局变量在技术上不是真正的变量,但它们是全局对象的属性。可以使用 delete 运算符删除属性,而变量不能:

// define three globals
var global_var = 1;
global_novar = 2; // antipattern
(function () {
   global_fromfunc = 3; // antipattern
}());
// attempt to delete
delete global_var; // false
delete global_novar; // true
delete global_fromfunc; // true
// test the deletion
typeof global_var; // "number"
typeof global_novar; // "undefined"
typeof global_fromfunc; // "undefined"

In ES5 strict mode, assignments to undeclared variables (such as the two antipatterns in the preceding snippet) will throw an error.

在 ES5 严格模式下,对未声明变量(例如前面代码段中的两个反模式)的赋值将引发错误。

JavaScript Patterns, by Stoyan Stefanov (O'Reilly). Copyright 2010 Yahoo!, Inc., 9780596806750.

JavaScript 模式,作者:Stoyan Stefanov (O'Reilly)。版权所有 2010 Yahoo!, Inc.,9780596806750。

回答by Guffa

The only use of global variables is if you need to access them globally. In that case you should declare them using the varkeyword outside the functions, to make it clear that you really want to create global variables, and didn't just forget the varwhen trying to declare a local variable.

全局变量的唯一用途是如果您需要全局访问它们。在这种情况下,您应该var在函数外部使用关键字来声明它们,以明确表示您确实想要创建全局变量,而不是var在尝试声明局部变量时忘记了。

Generally you should try to scope your code so that you need as little as possible in the global scope. The more global variables you use in your script, the less is the chance that you can use it along side another script.

通常,您应该尝试限定代码的范围,以便在全局范围内尽可能少地需要。您在脚本中使用的全局变量越多,将其与另一个脚本一起使用的机会就越少。

Normally variables in a function should be local, so that they go away when you exit the function.

通常函数中的变量应该是局部的,这样当你退出函数时它们就会消失。

回答by brezanac

Sometimes its useful to create new globally accessible properties inside functions which can later be easily accessed by referencing the window object (all globally declared properties are attached to the window object).

有时在函数内部创建新的全局可访问属性很有用,以后可以通过引用 window 对象轻松访问这些属性(所有全局声明的属性都附加到 window 对象)。

However as it usually is with declaring anything to be globally accessible it can lead to problems later because those properties can be easily overwritten etc. Its far better to simply pass values to functions as arguments and retrieve their results.

然而,正如通常声明任何东西可以全局访问一样,它可能会在以后导致问题,因为这些属性很容易被覆盖等。简单地将值作为参数传递给函数并检索它们的结果要好得多。

回答by QuentinUK

The main problem is someone else may already be using a global with the same name.

主要问题是其他人可能已经在使用同名的全局变量。

Then when you change the value of the global you'll overwrite their value.

然后,当您更改全局值时,您将覆盖它们的值。

Later on when the global is next used it will have mysteriously changed.

稍后在下一次使用全局时,它会发生神秘的变化。

回答by Ed_Johnsen

Declaring a variable inside of a function without the use of var, let, or const is no more useful inside the function than is declaring that variable with var, let, or const. And, as noted in previous answers to this question, function-local, implicit global declarations can be confusing and problematic outside the scope of the function where they were declared.

在不使用 var、let 或 const 的情况下在函数内部声明变量并不比在函数内部使用 var、let 或 const 声明该变量有用。而且,正如之前对这个问题的回答所指出的,函数局部的、隐式的全局声明在声明它们的函数范围之外可能会造成混淆和问题。

I'd like to speak to some subtleties that are missing from the w3schools quote, and from previous answers to this question.

我想谈谈 w3schools 引用以及之前对这个问题的回答中缺少的一些微妙之处。

First of all, if you never call the function that generates implicit globals, you won't generate any implicit globals. This is a subtle difference from the w3schools quote because it defies the "always" section of their statement.

首先,如果您从不调用生成隐式全局变量的函数,则不会生成任何隐式全局变量。这与 w3schools 的引用有细微的差别,因为它违背了他们声明中的“始终”部分。

function generateImplicitGlobals(){
  x = "x";
  window.y = "y";
}

// before calling the generateImplicitGlobals function, we can safely see that the x and y properties of the window object are both undefined:
console.log("before calling the generateImplicitGlobals function, properties x and y of the window object are: " + window.x + " and " + window.y);

// before calling the generateImplicitGlobals function, we can test for the existence of global variables x and y; note that we get errors instead of undefined for both.
try{
  console.log("before calling the generateImplicitGlobals function, x is: " + x);
}
catch(e){
  console.log("before calling the generateImplicitGlobals function, an attempt to reference some global variable x produces " + e);
}

try{
  console.log("before calling the generateImplicitGlobals function, y is: " + y);
}
catch(e){
  console.log("before calling the generateImplicitGlobals function, an attempt to reference the global variable b also produces " + e);
}
诚然,我确信 w3schools 知道函数内部的隐式全局声明不是在调用函数之前进行的,但是,对于 javascript 新手来说,从给定的信息中可能不清楚。

Regarding subtleties of previous answers, once the generateImplicitGlobals function has been called, we can see that attempts to access either the window.x property or the global variable x return the same values (and that the window.y property and the global y variable return the same values). These statements are true when called from inside or outside the generateImplicitGlobals function.

关于先前答案的微妙之处,一旦调用 generateImplicitGlobals 函数,我们可以看到尝试访问 window.x 属性或全局变量 x 返回相同的值(并且 window.y 属性和全局 y 变量返回相同的值)。当从 generateImplicitGlobals 函数内部或外部调用时,这些语句为真。

function generateImplicitGlobals(){
  x = "x";
  window.y = "y";
  console.log("inside the function, x and window.x are: " + x + " and " + window.x);
  console.log("inside the function, y and window.y are: " + y + " and " + window.y);
}

// now, call the generator, and see what happens locally and globally.
generateImplicitGlobals();
console.log("after calling the generateImplicitGlobals function, x, window.x, y, and window.y are: " + x + ", " + window.x + ", " + y + ", and " + window.y);

回答by Erik Rybalkin

I would say that it might hurt your security and even stability of your code.

我会说它可能会损害您的安全性甚至代码的稳定性。

As was mentioned above, you might make a mistake by simply misspelling your variables and a solution is the keyword "use strict";
With this keyword declared it will throw you an error: Uncaught ReferenceError: foo is not defined.

如上所述,您可能会因为简单地拼错变量而犯错误,而解决方案是"use strict";
关键字 声明此关键字后,它会抛出错误:Uncaught ReferenceError: foo is not defined

It also refers to a secured code:
1. When writing a secured code, we do not want our variables to be accessed anywhere besides where they were actually declared. Do not declare global variables without the need.
2. Always read warnings carefully and resolve them. Use "use strict";, JSlint and other tools to see and resolve warning to make your code better.

它还指的是安全代码:
1. 在编写安全代码时,我们不希望我们的变量在实际声明的地方之外的任何地方被访问。不要在不需要的情况下声明全局变量。
2. 务必仔细阅读警告并解决它们。使用"use strict";、JSlint 等工具查看和解决警告,使您的代码更好。