JavaScript声明提升
声明提升就好像把声明(变量声明和函数声明)从它们所在代码中出现的位置移到了最上面。直觉上我们会以为JavaScript代码是由上到下一行一行执行的,但实际上这并不完全正确,还要考虑声明提升的存在。
题目1:
var a = 99; // 全局变量a
f(); // f是函数,虽然定义在调用的后面,但是函数声明会提升到作用域的顶部。
console.log(a); // a=>99, 此时是全局变量的a
function f() {
console.log(a); // 当前的a变量是下面变量a声明提升后,默认值undefined
var a = 10;
console.log(a); // a => 10
}
// 输出结果:
undefined
10
99
在实际开发中,很多程序员把a=0写成var a=0;但实际上它们差别很大 我们习惯性的 把var a = 2; 看做一个声明,而实际上JavaScript引擎并不这么认为。它将 var a 和 a = 2 当做两个单独的声明, 第一个是编译阶段的任务,而第二个则是执行阶段的任务。只有声明本身会被提升,而赋值或其他运行逻辑会留在原地。
var a;
a = 2;
console.log(a); // 2
var a;
console.log(a); // undefined
a = 2;
声明提升实例:
fn();
/**
*
*/
function fn(){
console.log(a); // ??
var a = 2;
}
/**
*等同于上面
*/
function fn2(){
var a;
console.log(a); // undefined
a = 2;
}
function方法的声明也一样 函数声明会被提升,但是函数表达式却不会被提升。
fn();
var fn = function (){
console.log(a);
var a = 2;
}
// Uncaught TypeError: fn is not a function
函数声明和变量声明都会被提升,但是函数会首先提升,然后才是变量。即函数声明的优先级要大于变量声明。
声明提升优先级:
var yfun;
yfun(); // ??
function yfun(){
console.log(1);
}
按照声明提升的思路(相当于把所有声明提升的部分移到代码的最上面然后在一行一行顺序执行),上面的两段代码相当于:
function yfun(){
console.log(1);
}
var yfun; // 重复声明,被忽略
yfun(); // 1
尽管var yfun出现在function yfun之前,但是函数提升的优先级要大于变量提升,所以 function yfun(){} 会在var yfun之前;但是var yfun是重复声明所以被忽略了,所以最终输出1。
在网上看到的一个函数声明的例子
var foo;
foo(); // 3
function foo(){
console.log(1);
}
function foo(){
console.log(3);
}
foo = function(){
console.log(2);
}
这个函数初始化运行时输出3,而如果页面内调用则会输出2, 原因就是函数提升
现在不少编辑器,如果直接运行js而不是浏览器环境,声明提升代码运行结果可能会报错函数或者变量不存在