也叫预解析,
进入作用域后 代码执行前,
用var声明的变量 声明提前 赋值不动
函数声明 声明提前 赋值提前
使得变量和函数在声明前就使用不会报错
<script>
var a = 1;
console.log(a);
function test(a) {
console.log(a);
var a = 123;
console.log(a);
function a() {}
console.log(a);
var b = function() {}
console.log(b);
function d() {}
}
var c = function (){
console.log("I at C function");
}
console.log(c);
test(2);
</script>
情况1:进入全局作用域
1.变量声明 变量名作为全局对象属性 值为undefined
2.函数声明 函数名作为全局对象属性 值为函数体
3.如果同名,函数声明覆盖变量声明
//抽象描述
GO/window = {
a: undefined,
test: function(a) {
console.log(a);
var a = 123;
console.log(a);
function a() {}
console.log(a);
var b = function() {}
console.log(b);
function d() {}
},
c: undefined,
}
情况2:进入函数作用域
- 创建AO活动对象(Active Object);
- 形参和变量声明 变量名作为AO的属性,值是undefined;
- 实参赋值给形参;
- 函数声明 函数名作为AO的属性,值是函数体;
- 如果同名,函数声明覆盖变量声明
//抽象描述
AO = {
a:function a() {},
b:undefined
d:function d() {}
}
情况3:进入块级作用域(es6)
相当于用var声明的函数表达式
// 浏览器的 ES6 环境
function f() { console.log('I am outside!'); }
(function () {
if (false) {
// 重复声明一次函数f
function f() { console.log('I am inside!'); }
}
f();
}());
// Uncaught TypeError: f is not a function
// 相当于如下代码
function f() { console.log('I am outside!'); }
(function () {
var f = undefined;
if (false) {
function f() { console.log('I am inside!'); }
}
f();
}());
// Uncaught TypeError: f is not a function
注意
1.变量前没有var ,则这个变量是全局变量
2.用let或const声明的变量,没有预编译(即变量提升)