javascript 执行分两步 1.预解析 2执行 执行的都是解析后的代码
1. 废话不多说,上代码。
console.log(a);
var a = 10
- 先想想这个执行结果是什么?
js解析完成
a = undefined
console.log(a); // undefined
a = 10;
- 执行结果是 undefined 这个过程叫变量提升。解析时遇到var 就会提升上去但并没有赋值。
2. 变形
console.log(b);
console.log(c);
function b() {
console.log("b");
}
var c = function() {
console.log("c");
}
js解析完成
function b() {
console.log("b");
}
c = undefined;
console.log(b); // function b() { console.log("b") }
console.log(c); // undefined
c = function() {
console.log("c");
}
- 同样是函数,带var函数的函数表达式跟定义一个变量都有相同效果。提升并不赋值。 而函数则不同,函数声明会直接提升到顶部。
我们记住两点 在预解析阶段 有函数提升和变量提升两个动作。
3. 继续加强
(functino(){
console.log(a); // undefined
var a = 10;
})()
function start(){
console.log(b); // function b() { console.log("b") }
console.log(c); // undefined
function b() {
console.log("b");
}
var c = function() {
console.log("c");
}
}
start();
变量提升发生在当前的函数作用域内。 自执行函数和函数都有提升过程。
4. 无var的情况
(function(){
b = 10;
})()
console.log(b);
js 解析完成
(function(){
b = 10;
})()
console.log(b); // 10
没有声明的变量b在解析阶段并没有提升,js执行器在发现b没有在当前作用域声明时会在执行阶段提升到全局。所以外面可以访问到 。 如果在执行阶段提前打印b会直接报错停止运行。
5. 特殊情况
5.1 例1
(function(){
console.log(b);
var b = 10;
function b(){
console.log("fn");
}
console.log(b);
})()
解析完成
(function(){
function b(){
console.log("fn");
}
console.log(b); // function b(){console.log("fn"); }
b = 10;
console.log(b); // 10
})()
当函数生命和var声明同时存在的时候 函数声明优先级高 这个要注意
5.2 例2
function start(b){
start = 10;
console.log(start);
console.log(b);
b = 10;
}
start();
console.log(b);
解析完成
function start(){
b = undefined;
start = 10;
console.log(start); // function start(b){ ... }
console.log(b); // undefined
b = 10;
}
start();
console.log(b); // err b is not defined
在函数内部有参数时 b 就会声明在函数内部。 而给函数名本身赋值是无效的。
结束
还有更多js的解析过程需要大家发现。例如异步代码。setTimeout Promise 等等执行过程 这里列举在函数解析过程当中的常见问题。比如 let const 就没有提升过程。