Hoisting声明提升
JavaScript程序在运行前有一个预编译的过程,而声明提升就发生在预编译的过程
预编译规则
-
对var关键字提前声明(值先设为undefined,执行时才给实际值)
if ("a" in window) {
var a = 1;
}
console.log(a);
//等价于
var a;
if("a" in window){
a = 1;
}
console.log(a);
-
对函数定义式进行提前(函数表达式不提前)
a(); function a(){ console.log("Hello"); }
//等价于
function a(){
console.log("Hello");
}
a();
//函数表达式不提前
a();
var a = function (){
console.log("Hello");
}
-
变量的解析顺序(优先级),与变量进入作用域的4种方式的顺序一致
在JavaScript,一个变量名进入作用域的顺序:
-
Language-defined(语言内置):所有的作用域中都有 this 和
arguments 关键字 -
Formal parameters(形式参数):函数的参数在函数作用域中都是有
效的 -
Function declarations(函数声明):形如function foo() {}
-
Variable declarations(变量声明):形如var bar;
-
function testOrder(arg) {
console.log(arg); // arg是形参,不会被重新定义
console.log(a); // 因为函数声明比变量声明优先级高,所以这里a是函数
var arg = 'hello'; // var arg;变量声明被忽略, arg = 'hello'被执行
var a = 10; // var a;被忽视; a = 10被执行,a变成number
var b = 20;
function a() {
console.log('fun');
} // 被提升到作用域顶部
console.log(a); // 输出10
console.log(arg); // 输出hello
console.log(b);
};
testOrder('hi');
等价于:
function testOrder(arg) {
// Language-defined this && arguments
// 形参 arg
//函数声明
function a() {
console.log('fun');
}
//变量声明
var b;
console.log(arg); // arg是形参,不会被重新定义
console.log(a); // 因为函数声明比变量声明优先级高,所以这里a是函数
arg = 'hello'; // var arg;变量声明被忽略, arg = 'hello'被执行
a = 10; // var a;被忽视; a = 10被执行,a变成number
b = 20;
console.log(a); // 输出10
console.log(arg); // 输出hello
console.log(b);
};
testOrder('hi');
ES2015
* ES5只有两种声明变量的方法:var 和 function。
* ES6添加了let,const,class 和 import。所以,ES6一共有6种声明变量的方法。(let,const,class不存在变量提升)