var 关键字的用途是什么,我应该什么时候使用(或省略它)?

IT技术 javascript keyword ecmascript-5
2020-12-23 23:49:09

注意:这个问题是从 ECMAScript 版本 3 或 5 的角度提出的。随着 ECMAScript 6 版本中新功能的引入,答案可能会过时。

varJavaScript中关键字的作用到底是什么,和有什么区别

var someNumber = 2;
var someFunction = function() { doSomething; }
var someObject = { }
var someObject.someProperty = 5;

someNumber = 2;
someFunction = function() { doSomething; }
someObject = { }
someObject.someProperty = 5;

?

你什么时候会使用任何一种,为什么/它有什么作用?

6个回答

如果您在全局范围内,则没有太大区别。阅读Kangax 的回答以获取解释

如果您在一个函数中,那么var将创建一个局部变量,“no var”将查找作用域链,直到找到该变量或命中全局作用域(此时它将创建它):

// These are both globals
var foo = 1;
bar = 2;

function()
{
    var foo = 1; // Local
    bar = 2;     // Global

    // Execute an anonymous function
    (function()
    {
        var wibble = 1; // Local
        foo = 2; // Inherits from scope above (creating a closure)
        moo = 3; // Global
    }())
}

如果您不做作业,则需要使用var

var x; // Declare x
是“差别不大”==“没有差别”吗?
2021-02-08 23:49:09
嗯,实际上是的,有区别:) 这种区别是否重要是另一个问题。进一步查看我的答案:stackoverflow.com/questions/1470488/...
2021-02-11 23:49:09
我认为这可能是 Alex 的观点,这就是他使用“等于”运算符编写它的原因!
2021-02-16 23:49:09
这就像用轨道炮射击自己......忘记在一个变量之前放置一个'var',最终修改了范围链中某处的变量......尝试说服Java / C / Python / etc。开发人员认为 JavaScript 值得。哈!相比之下,C/C++ 陷阱看起来不错。想象一下必须调试 JavaScript……当然,有些人会这样做。还有很多代码(注意,不是简单的代码)是用 JavaScript 编写的……
2021-02-26 23:49:09
如果您在全局范围内,则没有区别。>> 有一个不同之处,在下面的答案中进行了解释
2021-03-06 23:49:09

有区别

var x = 1 x在当前范围(又名执行上下文)中声明变量如果声明出现在函数中 - 声明了一个局部变量;如果它在全局范围内 - 声明了一个全局变量。

x = 1,另一方面,只是一个财产分配。它首先尝试x针对作用域链进行解析如果它在作用域链中的任何地方找到它,它就会执行赋值;如果它没有找到x,那么x才会在全局对象(它是作用域链中的顶级对象)创建属性

现在,注意它没有声明一个全局变量,它创建了一个全局属性。

两者之间的区别很微妙并且可能会令人困惑,除非您了解变量声明也创建属性(仅在变量对象上)并且 Javascript 中的每个属性(好吧,ECMAScript)都有某些描述其属性的标志 - ReadOnly、DontEnum 和不要删除。

由于变量声明创建了带有 DontDelete 标志的属性,var x = 1x = 1(在全局范围内执行时)之间的区别在于前者 - 变量声明 - 创建了 DontDelete'able 属性,而后一个则没有。因此,通过这种隐式赋值创建的属性可以从全局对象中删除,而前一个 - 通过变量声明创建的属性 - 不能删除。

但这当然只是理论,在实践中,由于实现中的各种错误(例如来自 IE 的错误),两者之间还有更多差异

希望这一切都有意义:)


[更新 2010/12/16]

在 ES5(ECMAScript 5;最近标准化,该语言的第 5 版)中有一种所谓的“严格模式”——一种选择加入的语言模式,它略微改变了未声明赋值的行为。在严格模式下,分配给未声明的标识符是ReferenceError这样做的基本原理是捕捉意外分配,防止创建不需要的全局属性。一些较新的浏览器已经开始滚动支持严格模式。例如,请参阅my compat table

如果我没记错的话,我想我曾经找到一种方法可以delete通过一些evalhack 来声明 var 声明的变量如果我记得确切的技巧,我会在这里发布。
2021-02-07 23:49:09
@kangax 如果 Alex 示例的最后两行是混合的怎么办var someObject = {}someObject.someProperty = 5someProperty变成全局的,而它是一个属性的对象仍然是本地的吗?
2021-02-09 23:49:09
有点偏离主题,但在此提及以供参考。“let” 与“var”非常相似,Mozilla 支持。主要区别在于 var 变量的范围是整个封闭函数,而“let”仅限于其块
2021-02-11 23:49:09
@Mageek 他可能正在考虑可删除的 eval 声明的变量。我曾经写过一篇关于这个博客文章
2021-02-22 23:49:09
@kangax 称为DontDelete标志的规范名称是可配置的 (= false),您可以阅读有关Object.definePropertyObject.getOwnPropertyDescriptor
2021-03-06 23:49:09

说这是“本地全球之间的区别并不完全准确。

最好将其视为“本地最近之间的区别最近的肯定可以是全局的,但情况并非总是如此。

/* global scope */
var local = true;
var global = true;

function outer() {
    /* local scope */
    var local = true;
    var global = false;

    /* nearest scope = outer */
    local = !global;

    function inner() {
        /* nearest scope = outer */
        local = false;
        global = false;

        /* nearest scope = undefined */
        /* defaults to defining a global */
        public = global;
    }
}
我想知道如果您将该行更改为var global = local;在这种情况下 local 的 Nears 范围将是正在积极定义的“本地”外部范围,您的评论是否会改变尽管如果您将同一行更改为var global = global在这种情况下搜索的值时最近的范围global会在全局窗口范围内上升一个级别,这会变得很奇怪
2021-02-12 23:49:09
@Snekse:当声明 <code>var global = false;</code> 时,'nearest' 不适用。在该声明中,'global' 被放置在 external() 的范围内,因为在声明中使用了 'var'。因为在inner() 中没有使用'var',它会改变下一个级别的值,即outer()。
2021-02-19 23:49:09
不是outer您定义的最近范围var global = false;吗?
2021-02-25 23:49:09

在浏览器中执行 Javascript 时,您的所有代码都被一个 with 语句包围,如下所示:

with (window) {
    //Your code
}

更多信息with- MDN

由于在当前范围内var声明了一个变量,因此在 window 内声明和根本不声明它之间没有区别var

当您不直接在窗口内时,例如在函数内或块内,差异就出现了。

Usingvar允许您隐藏具有相同名称的外部变量。通过这种方式,您可以模拟“私有”变量,但这是另一个话题。

经验法则是始终使用var,否则您将面临引入细微错误的风险。

编辑:在收到批评之后,我想强调以下几点:

  • var在当前作用域中声明一个变量
  • 全局范围是 window
  • 不在全局范围内使用var隐式声明var(窗口)
  • 在全局范围(窗口)中声明变量 usingvar与省略它相同。
  • 声明在使用窗口不同的范围的变量var 是不一样的东西作为声明的变量,而不var
  • 始终var明确声明,因为这是很好的做法
我只是用它的名字来称呼事物,你想称它为“全局作用域”,没关系,但是按照惯例,客户端是窗口对象,它是作用域链的最后一个元素,这就是为什么你可以调用每个函数和窗口中的每个对象不写“窗口”。
2021-02-07 23:49:09
+1 这是一个非常好的解释——我以前从未听说过像这样构建的 var/no var 问题(没有双关语)。
2021-02-08 23:49:09
我没有贬低你,但范围可能比窗口更好。你的整个解释有点迟钝。
2021-02-11 23:49:09
这个答案的大部分内容let在 ES6 中已被弃用
2021-02-14 23:49:09
@EvanCarroll 这个答案在技术上也是不正确的,因为省略 var 没有声明任何变量,而是在全局对象上创建了一个可删除的属性,除了 ES5“使用严格”模式之外,大多数答案显然是不正确的,也不是'在这个答案中甚至没有考虑过,因为在提出问题时没有任何对 javascript 版本(昨天添加)的引用,这意味着参考标准(当时)是 ECMA 262 3rd Edition。
2021-02-17 23:49:09

始终使用var关键字来声明变量。为什么?良好的编码实践本身应该是一个足够的理由,但省略它意味着它是在全局范围内声明的(像这样的变量被称为“隐含的”全局)。Douglas Crockford建议永远不要使用隐含的全局变量,并且根据Apple JavaScript 编码指南

任何没有使用var 关键字创建的变量都是在全局范围内创建的,并且在函数返回时不会被垃圾收集(因为它不会超出范围),这为内存泄漏提供了机会。

“良好的编码习惯”本身永远不应成为充分理由。它相当于“互联网上的一些人说这就是我的代码应该看起来的样子”。这甚至不如“我老师说的”那么有效,除非人们至少模糊地理解了规则背后的原因。
2021-02-15 23:49:09
@ChrisS:不,“良好的编码习惯”本身并不是理由。它被认为是良好实践原因很重要。除非这些作者告诉你他们推荐它的原因,否则他们的推荐应该没有任何分量。如果您不同意这些理由,那么您可以自由地将其视为糟糕的建议。如果你不问原因就遵循它,这就是货物崇拜的开始。
2021-02-17 23:49:09
@cHao 我认为good coding practice如果这是推荐的最佳实践,这总是足够的理由,这是由几位 Javascript 作者推荐的。
2021-02-26 23:49:09