JS的变量提升和函数声明提升顺序以及覆盖规则

//update:好吧我已经搞清楚了,会在时间限制后自己回答……

《你不知道的Javascript》里面说是函数声明提升优先

代码1

foo(); //输出1
var foo = function(){
  console.log(2)
}
function foo(){
  console.log(1)
}

会被解释为这样?为什么undefined的变量foo不会导致foo()抛错?书上说是因为重复声明所以被忽略,有没有相关资料参考下?

function foo(){
  console.log(1)
}
var foo;
foo(); //输出1
foo = function(){console.log(2)}

代码2

var foo = function(){
  console.log(2)
}
function foo(){
  console.log(1)
}
foo();//输出2

会被解释为这样?

function foo(){
  console.log(1)
}
var foo;
foo = function(){console.log(2)}
foo();//输出2
阅读 5.9k
3 个回答

自己回答

规则是:
对于同名的变量声明,Javascript采用的是忽略原则,后声明的会被忽略,变量声明和赋值操作可以写在一起,但是只有声明会被提升,提升后变量的值默认为undefined,结果是在赋值操作执行前变量的值必为undefined

对于同名的函数声明,Javascript采用的是覆盖原则,先声明的会被覆盖,因为函数在声明时会指定函数的内容,所以同一作用域下一系列同名函数声明的最终结果是调用时函数的内容和最后一次函数声明相同

对于同名的函数声明和变量声明,采用的是忽略原则,由于在提升时函数声明会提升到变量声明之前,变量声明一定会被忽略,所以结果是函数声明有效

同名函数声明

function foo(){console.log(1)}
function foo(){console.log(2)}  //覆盖第一行
foo() //2

同名变量

var foo = function(){console.log(1)}
var foo = function(){console.log(2)}
foo()

会被解析为

var foo
var foo //被忽略
foo = function(){console.log(1)}
foo = function(){console.log(2)}

同名变量和函数声明

function foo(){
  console.log(1)
}
var foo; //被忽略
foo(); //1
新手上路,请多包涵

理解清楚,申明和赋值的顺序,2个维度的问题。
首先把所有的申明提前,并且函数申明在变量申明之前
再赋值操作。
回到问题

foo() // 这里先把所有的申明提前,函数申明的优先级更高,所以do something
var foo = function(){
    // do something else
}
function foo(){
    // do something
}

还有一个demo

function foo(){
  // do something
}
var foo;
foo = function(){
    // do something else
}
foo();//foo最开始申明是do something,但是调用之前又做了赋值操作,所以do something else
新手上路,请多包涵

补充一个demo:
var a=undefined; function () {console.log(1)}; a();
//=>Uncaught TypeError: a is not a function

原因:变量声明分为两步。var a=undefined;会被编辑器解析为var a; a=undefined;两步来执行,第一步定义声明var a; 在编译阶段,第二步赋值声明 a=undefined;在执行阶段。所以此处执行过程是:function a(){};
var a;
a=undefined;
a()

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏