1.变量声明提升
定义变量方式
- ES5:
var定义 - ES6:
let / const,块级作用域无法进行变量提升。
var 定义变量----声明的变量会提升到代码顶部
//原始代码
console.log(a) // undefined;
var a = 1;
//提升后
var a;
console.log(a)
a = 1;
let / const 无法进行变量提升
console.log(a) // a is not defined
let a = 1;
console.log(c) // c is not defined
const c = 1;
2.函数声明提升
函数的声明方式有两种:自定义函数声明方式(命名函数)和函数表达式方式(匿名函数);
只有自定义函数声明方式才存在函数提升!!
foo(); // 1
function foo() {
// 自定义函数声明的形式,函数会提升到顶部
console.log('1');
}
var foo = function() {
// 函数表达式的方式,则等同于一个变量提升,优先级小于函数提升
console.log('2');
}
上述代码会被引擎解析为:
function foo() {
console.log('1');
}
var foo;
foo();
foo = function() {
console.log('2');
}
引擎的解析器规则是什么呢?
解释规则:解析器会事先读取函数声明,即函数声明放在任意位置都可以被调用。但是对于函数表达式,解析器只有读取到函数表达式所在的位置才能执行;
变量提升和函数提升的优先级
👉👉 变量与函数之间,函数会被优先进行提升,然后才是变量。
console.log(a);
// ƒ a() { console.log('a') var b = '2'; console.log(b); }
var a;
var b = '1';
function a() {
console.log('a') //a
var b = '2';
console.log(b); //2
}
a();
👉👉 函数提升不会被变量声明覆盖,但是会被变量覆盖
console.log(a);
// ƒ a() { console.log('a') var b = '2'; console.log(b); }
var a = 5;
var b = '1';
function a() {
console.log('a')
var b = '2';
console.log(b);
}
a(); // a is not a function
👉👉 函数内部变量提升优先级高于函数外部变量提升
//情形1:
var a = 5;
function b() {
console.log(a) // undefined
var a = '2';
console.log(a); //2
}
b();
//情形2:
var a = 5;
function b() {
console.log(a) // 5
}
b();
上述涉及到作用域的问题(如果函数内部使用var声明了和外部变量相同的名称,函数将不再向上寻找,反之会向上寻找)
总结
- 函数提升高于变量提升
- 函数提升只有自定义函数声明才会发生函数提升,函数表达式方式不会提升。
- 函数提升的优先级高于变量提升,且不会被变量声明覆盖,但是会被变量赋值覆盖
- 如函数内部使用var声明了和外部变量相同的名称,函数将不再向上寻找,反之会向上寻找