协慌网

登录 贡献 社区

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

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

JavaScript 中var关键字的功能到底是什么,有什么区别

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

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

你什么时候使用其中任何一个,为什么 / 它做什么?

答案

如果你在全球范围内,则没有太大区别。阅读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

有区别

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

另一方面, x = 1仅仅是属性赋值。它首先尝试针对作用域链解析x 。如果它在该范围链中的任何位置找到它,它将执行赋值; 如果它找不到x ,那么才会在全局对象 (它是作用域链中的顶级对象) 上创建x属性

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

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

由于变量声明使用 DontDelete 标志创建属性,因此var x = 1x = 1 (在全局范围内执行时)之间的差异是前者 - 变量声明 - 创建 DontDelete'able 属性,而后者不属性。因此,可以从全局对象中删除通过此隐式赋值创建的属性,并且不能删除前一个 - 通过变量声明创建的属性。

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

希望这一切都有道理:)


[更新 2010/12/16]

在 ES5(ECMAScript 5; 最近标准化,第 5 版语言)中,有一种所谓的 “严格模式” - 一种选择加入语言模式,它稍微改变了未声明的作业的行为。在严格模式下,对未声明标识符的赋值是ReferenceError 。其基本原理是捕获意外分配,防止产生不希望的全局属性。一些较新的浏览器已经开始支持严格模式。例如,请参阅我的 compat 表

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

将它视为 “ 本地最近 ” 之间的区别可能更好。最近的肯定是全球性的,但情况并非总是如此。

/* 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;
    }
}