我正在以三种方式修改一段代码。在这3个条件中表现不同。请描述一下它是如何执行的?
var a=1;
function myFunc(){
console.log(a);
console.log(a)
}
myFunc();
//Output is:
1
1
var a=1;
function myFunc(){
console.log(a);
var a=2;
console.log(a)
}
myFunc();
//Output is:
undefined
2
var a=1;
function myFunc(){
console.log(a);
var a=2;
console.log(a)
}
myFunc(a);
//Output is:
undefined
2
为什么在第二种情况下它的打印未定义?在第三种情况下,我发送我的全局a作为参数,然后它也是未定义的打印。
答案 0 :(得分:16)
那是因为JavaScript将var声明移到了作用域的顶部,所以你的代码实际上是:
var a = 1;
function myFunc(){
var a; // a is redeclared, but no value is assigned
console.log(a); // therefore it evaluates to undefined
a = 2; // now a = 2
console.log(a); // and then it logs to 2
}
myFunc();
此行为称为Variable Hoisting。
修改强>
正如Beterraba所说,在第三个代码中它记录undefined
因为在函数头中没有声明参数:
var a = 1;
function myFunc(a) { // a is declared
console.log(a); // now a logs 1
var a = 2; // now a = 2
console.log(a);
}
myFunc(a);
答案 1 :(得分:2)
第二种情况是由于JavaScript执行上下文的工作方式而打印未定义。您可能遇到过吊装这个词。
为了更详细地解释它,当调用第二个函数时,解释器将进入一个包含两个阶段的过程。
创作阶段
激活或代码执行阶段
因此,当您调用myFunc()
时,JavaScript解释器将创建一个执行上下文,您可以将其视为对象文字,如下所示:
myFuncExecutionContext = {
scopeChain: { ... },
variableObject: {
arguments: {
length: 0
},
a: undefined,
},
this: { ... }
}
您可以看到本地变量的初始值为undefined。在代码执行阶段,解释器将逐行运行函数;所以它看到的第一行是console.log(a);
。解释器将查看variableObject
以查看是否存在具有该名称的变量。如果不是,它将使用作用域链并尝试在外部作用域的变量对象中找到它。因为,变量对象中有a
变量,它将读取它的值,这是未定义的。
然后它将执行第2行,它将为局部变量a赋值; var a=2;
。然后它将执行最后一行 - console.log(a)
- 它将打印我们之前分配的值。
同样的机制证明了为什么我们可以在定义函数之前调用它,只要我们使用函数声明语法。
someFunc(); // VALID
function someFunc(){ };
以下情况会导致错误:
someFunc(); // TypeError: undefined is not a function
var someFunc = function() { }