如果在定义之前我可以在JS中使用变量,我一直想知道, 如下:
var country = "USA";
switch (country) {
case "USA":
country = i;
case "blach":
//not finished yet
}
/*
put a whole
bunch more code here
*/
var i = 10;
这有效吗?是允许的吗?如果是这样,它的技术术语是什么?
答案 0 :(得分:24)
这是一种名为hoisting的JavaScript引擎使用的技术。解析器将在运行之前读取整个函数,并且将执行任何变量声明(即使用var
关键字),就好像它们位于包含范围的顶部一样。所以你的代码就像:
var country;
var i;
country = "USA";
switch (country) {
case "USA":
country = i;
case "blach":
//not finished yet
}
i = 10;
因此,i
在整个范围内声明,但在undefined
语句运行之前,其值为i = 10
。
在ECMAScript术语中,当调用函数时,函数的新词法范围在任何函数的代码运行之前构建其VariableEnvironment
。在ECMAScript 10.5, step 8:
8。对于代码中的每个 VariableDeclaration ... d ,在源文本顺序中执行
一个。设 dn 为d。
中的标识符...
我。调用 env 的CreateMutableBinding具体方法,将 dn 和 configurableBindings 作为参数传递。
II。调用 env 的SetMutableBinding具体方法,将 dn ,
undefined
和 strict 作为参数传递。
这是非常满口的,但基本上它说:
在运行函数之前,请查看函数的源代码,了解
var [identifierName]
之类的声明。对于您找到的每个声明,在函数的作用域中创建一个新变量,声明中使用名称
[identifierName]
,然后将其值设置为undefined
答案 1 :(得分:7)
它被称为variable hoisting,这是一个很好的概念,因为它偶尔可以创建很难追踪的错误。
例如:
var stuff = 'stuff';
function() {
console.log(stuff); //outputs 'undefined'
var stuff = 'other stuff';
console.log(stuff); //outputs 'other stuff'
}
第一个console.log
输出undefined
,因为函数中的var stuff
被提升到函数的顶部。
//theoretical compiled output
var stuff = 'stuff';
function() {
var stuff; //has not been defined
console.log(stuff);
stuff = 'other stuff'; //defined here
console.log(stuff);
}
如果不知道变量提升,这个结果可能会令人困惑。
因此,如果您查看专业开发的JavaScript代码,通常会看到函数中的所有变量都在顶部声明。
答案 2 :(得分:3)
是。在JavaScript中,变量为hoisted
变量语句声明按10.5中定义的方式创建的变量。 变量在创建时初始化为未定义。具有Initialiser的变量在执行VariableStatement时被赋予其AssignmentExpression 的值,而不是在创建变量时。 ES5 §12.2
其中10.5步骤8是感兴趣的部分
答案 3 :(得分:2)
这些家伙的答案是正确的。但是,对于您的示例,值得注意的是country
是undefined
。因为aspillers提到你的代码行为如下
var country;
var i;
country = "USA";
switch (country) {
case "USA":
country = i;
case "blach":
//not finished yet
}
i = 10;
alert(country) //undefined;
但是当您的case
语句针对“USA”运行时,i
未定义,因此已将其分配给country
。请在此fiddle中尝试。
我想你只需要知道虽然变量声明是悬挂的,但值赋值不是。