es5:函数作用域、全局作用域 (var 、function有变量提升)
es6:块级作用域 (没有变量提升) (let、const)
先来说说变量提升:
1、变量提升
(function () {
console.log(a); //undefined
console.log(b); //undefined
console.log(c); //undefined
console.log(d); //ƒunction d() { }
var a;
var b =3;
var c = function () { };
function d() { };
})();
可见,单纯的声明会提升,
定义变量,则提取其声明操作提升,
函数声明会完全提升
2、在提升的时候发生重命名了
(function () {
function a() { };
console.log(a);
var a = 12;
console.log(a);
var a = "aaa";
console.log(a);
})();
结果:
function a (){}
12
aaa
相当于
(function () {
function a() { };
var a;
var a;
console.log(a);
a = 12;
console.log(a);
a = "aaa";
console.log(a);
})();
Q1:var a为什么没有覆盖掉function a(){}这个定义,使第一个打印为undefined?
因为编译器在遇到变量声明时(函数表达式可以理解为包含了声明和赋值的操作),会先查看当前作用域,如果该变量不存在,则在该作用域中声明该变量;如果存在,则会忽略该声明。
3、hoisting中的函数声明
(function () {
console.log(a);
console.log(b);
{
function a() {alert("hha")}
}
function b() {}
})();
结果为:
undefined
function b(){}
直接在函数体内定义的函数声明,整个都会提前;
但是在块中定义的函数声明,只会提升其声明部分,不分配实际的内存空间
当将代码看成一个IIFE时,全局作用域其实就是一个函数作用域。
Q2那么函数作用域跟块级作用域的区别是什么呢?
- 函数作用域:变量在定义的函数内及嵌套的子函数内处处可见;
- 块级函数域:变量在离开定义的块级代码后马上被回收。
Q3:那么为什么两者会有这样的区别呢?
因为在函数作用域内,变量声明有一个提升hoisting的过程。
给出几个简单的例子
function aaa(){
var a=b=10;
}
aaa();
alert(a);//结果报错a is not defined
function aaa(){
var a=b=10;
}
aaa();
alert(b);//结果为10
var a=10;
function aaa(){
console.log(a);
var a = 110;
};
function bbb(){
var a=20;
aaa();
}
bbb();
//结果为undefined;