2014-02-19 181 views
10

我正在用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作为参数,然后打印未定义。

+1

一句话:吊装。这是一个很好的链接:http://www.adequatelygood.com/JavaScript-Scoping-and-Histing.html –

+0

这被称为[变量提升](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var#var_hoisting) –

+1

http://www.adequatelygood.com/JavaScript-Scoping-and-Histing.html – ashley

回答

16

这是因为JavaScript的移动变种声明的范围的顶部,因此您的代码实际上是:

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); 
+0

技术术语是'hoisting',顺便说一句。 – Langdon

+0

谢谢,我正试图记住。 –

+0

而第三种情况不起作用,因为他没有收到函数中的任何参数。 – Beterraba

2

第二种情况是打印未定义由于方式的JavaScript执行上下文作品。你可能会遇到的提升

要更详细地解释它,当第二个函数被调用时,解释器将进入一个有两个阶段的进程。

创作阶段

  • 创建范围链
  • 创建参数,函数,变量,即所谓的可变对象
  • 确定的关键字 “this” 值

激活或代码执行阶段

  • 解释,当你调用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() { } 
相关问题