我很想知道声明变量和初始化变量之间的区别。 e.g。
var example; // this is declaring
var example = "hi" // initializing? Or just "adding a value"?
我不认为我就在那里,但每个人的定义究竟是什么?或者他们基本上是同一个意思?
答案 0 :(得分:12)
编辑:@ThisClark在评论中说了些什么,我去证明他是错的,在阅读规范后我学到了更多东西:
之外,这里提供了丰富的信息
var
语句声明了作用于正在运行的执行上下文的VariableEnvironment的变量。 Var变量在实例化包含词法环境时创建,并在创建时初始化为undefined
。 [...]在执行VariableDeclaration时,由VariableDeclaration和Initializer定义的变量被赋予其Initializer的AssignmentExpression的值,而不是在创建变量时。
根据我对此的解读,以下几点描述了您在问题中询问的行为(以及"正确用法和#34;条款的用法):
变量声明(例如,var foo
)会在" lexical环境&#34时立即导致该变量创建 ;被实例化。例如,如果该变量是在函数体中定义的,那么该函数就是"词法环境",因此变量创建与函数本身的实例化一致。
显然,变量声明可能会也可能不会使用初始值设定项创建(即,右侧表达式解析为变量' s初始值)。这是一个非常规范的术语"初始值"的使用,但是......让我们深入研究一下:
技术上,根据此处的规范说明,所有变量都使用值undefined
进行初始化:
变量已创建[...]并初始化为未定义
重视"技术上"在那里,如果还提供初始化程序,这在很大程度上是学术性的。
根据我们已经涵盖的内容,应该理解语句var foo;
可以在函数体内的任何地方存在,并将其移动到其他任何地方相同的函数对函数本身的运行时语义没有影响(无论是否/何处发生任何实际赋值或对foo
的其他引用)。如果这仍然令人困惑,请重新阅读之前的观点。
最后一点行为是最直观的部分,它是初始化程序的作业。当这行代码实际上是执行时,就会发生这种分配(同样,在技术上已经创建的变量时,它不是同一时间点)。 / p>
所以,快速回顾一下:
var
)始终在其词法环境初始化时使用undefined
进行初始化。希望有所帮助(而且我并没有非常误解规范!)。
答案 1 :(得分:3)
@ jmar777的答案绝对是规范的最佳解释和细分。但是,我发现对于我们实践的学习者来说,一些说明性的代码是有帮助的! ;)
基本理念
window.varName = value
)。undefined
(即使它们立即被分配了不同的值)第一行代码。)。因此,初始化不是一个对我们很重要的术语。我们声明并分配,Javascript引擎初始化。
所以直接回答你问题中的例子:
var example;
声明一个变量,在初始化期间会为其分配值undefined
。var example = "hi"
声明一个变量,最初也会为undefined
赋值,但是在执行期间实际到达该行代码时,会重新分配给字符串“hi”。
说明性代码
function testVariableDeclaration() {
// This behaves 'as expected'....
console.log(test2, 'no value assigned yet'); // --> undefined 'no value assigned yet'
// ....but shouldn't our actual expectation instead be that it'll throw an error since
// it doesn't exist yet? See the final console.log() below!
// As we all know....
test1 = 'global var'; // ....a variable assignment WITHOUT declaration in the current
// scope creates a global. (It's IMPLICITLY declared.)
// But a little counter-intuitively....
test2 = 'not global'; // Although this variable also appears to be assigned without
// declaration like 'test1', the declaration for 'test2' that
// appears *later* in the code gets hoisted so that it's already
// been declared in-scope prior to this assignment.
console.log( test1, window.test1 === test1 ); // --> 'global var' TRUE
console.log( test2, window.test2 === test2 ); // --> 'not global' FALSE
var test2; // As shown by the above console.log() outputs, this variable is scoped.
console.log( test3 ); // Throws a ReferenceError since 'test3' is not declared
// anywhere, as opposed to the first console.log() for 'test2'.
}
'范围'对声明/指定的影响
声明和赋值之间的区别更明显的是声明变量总是在当前作用域内创建一个新变量(myVar
scopeB ),即使在父作用域中存在同名变量(myVar
scopeA )。然后,我们可以在当前范围内的任意位置1> scopeB ,而无需重新声明它。 (此作业不会影响myVar
scopeA 的值。)一旦 scopeB 结束已到达,myVar
scopeB 将不再可用于分配。
另一方面,如果我们为给定范围中的变量赋值,而在该范围内声明它,则它将被分配给'中的下一个最高级别的声明'范围链'(如果没有找到更高的声明,则隐式声明全局)。
因此,变量只需要在每个范围中声明一次,每个声明都会覆盖父范围内的任何声明(即它创建一个不同的变量)。但是必须在范围内声明,如果它对于该范围是唯一的。赋值可以根据需要多次发生,但只会影响最“紧密声明”的变量(缺少更好的术语)。
答案 2 :(得分:0)
宣言基本上是指在计划中引入新实体。初始化给出变量它的第一个值。所以基本上你的上面例子是正确的。
答案 3 :(得分:0)
声明是在程序中引入新名称。
var test; // Is this a declaration ?
初始化是指"赋值"价值观。
var test = {first:"number_one"} // Now that object is initialized with value
答案 4 :(得分:0)
唯一的区别是,var
语句将初始化任何声明的变量而没有undefined
的值。
在这两个示例中,您都声明了一个变量。
如果为没有var
语句的变量赋值,它将沿着范围链向下查找声明的变量,最终回退到全局window
对象。
答案 5 :(得分:0)
你在这里缺少一件小事。理解这个概念的类比是这样的。对于每个变量,必须为其分配一些值。
所有变量的默认值(如果未明确提及,则为未定义)
1) let example; // this is declaring and initializing with undefined
2) example="hi"; // this is assigning the value to hi
3) let example = "hi" // this is declaring and initializing with "hi"
所以第3个陈述实际上与1 + 2相同。
现在,可能会出现一个问题,即当陈述第3条成为可能时,为什么我们需要陈述1?
原因是扩大变量的范围。
e.g。让我们说第8行需要一个变量。但是这个值要么迟到才能在代码块中使用。
1) {
2) let a;
3) try{
4) a=someFunctionWhichMayThroeException();
5) }
6) catch(e){
7) a=100;
8) }
9) someFunctionOnA(a);// the variable is required here
10)
11) }
通过声明上面的变量,我们增加了变量的范围,因此可以在try块之外使用。
PS:这只是一个简单的用法示例。
答案 6 :(得分:-1)
直接从MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined:
全局undefined属性表示未定义的原始值。它是JavaScript的基本类型之一。
简单地在Javascript中声明变量,例如var example
将其初始化为undefined的原始值。这意味着以下两个表达式是等价的:
//equivalent expressions
var ex1;
var ex2 = undefined;
//true!
alert(ex2 === ex1);

我不知道并且此时无法测试的是网络浏览器历史记录中警报显示的真实程度。例如,此警报是否适用于IE6或一些模糊的Blackberry手机?我无法肯定地说这是通用的,但在撰写本文时它至少适用于最新版本的Firefox,Chrome和Safari。