变量、函数声明提升
其中有一个特点为: 函数会将代码块全部提升,而变量只会声明提升,不会将赋值解析到头部。
console.log(a);
var a = 1;
var b = 2;
console.log(a);
function a() {};
上面代码的解析方式为
var a;
var b;
function a() {};
console.log(a);
// ƒ a() {}
a = 1;
b = 2;
console.log(a);
// 1;
let,const
es6增加了块级作用域,而 let 和 const 定义的变量只在它所在的代码块有效,都不存在变量提升。
let
没有变量提升
{
console.log(a);
// ReferenceError: Cannot access 'a' before initialization
let a = 1;
}
{
console.log(a);
// undefined
var a = 1;
}
因此也出现了新的问题
// es5的情况
var demo = 1;
if (true) {
demo = 2;
// ReferenceError
let demo;
}
var 定义的全局变量 demo 在进入 if 区域块时又被 let 重新定义了,所以在 if 中 let 之前使用demo都是会报错的。这个报错的部分就是暂时性死区(temporal dead zone,简称TDZ)。
在es6之前 *typeof 绝对安全的,即使是一个没定义的变量也会输出“undefined“,在es6中就不再是百分百白安全。
{
typeof(age);
// undefined
}
{
typeof(age);
// ReferenceError
let age = 1;
}
const
const 特性与 let 相似,不存在变量提升,之作用于存在的代码块中,也会出现暂时性死区。
不同点在与 const 声明的变量不能改变值,本质是不能改变指向的地址的值。
// 简单数据类型
const cs = 1;
cs = 2
// TypeError: Assignment to constant variable.
// 复杂数据类型
const cs2 = {a:1, b:2}
cs2.a = 2
// print cs2
// {a: 2, b: 2}a: 2b: 2__proto__: Object
cs2 = {}
// TypeError: Assignment to constant variable.
如果想要一个复杂数据类型内容固定可使用方法 Object.freeze(obj) ,改变变量不会报,但是内容不会变化。
// print cs2
// {a: 2, b: 2}
Object.freeze(cs2)
// modify cs2 cs2.a = 3
// print cs2
// {a: 2, b: 2}
块级作用域中的函数声明
由于版本兼容问题,现在在块级作用域中声明的函数可以不遵守es6的规定,有自己的行为方式。
- 允许在块级作用域内声明函数。
- 函数声明类似于 var, 会提升到全局作用域或函数作用域的头部。
- 同时,函数声明还会提升到所在的块级作用域头部。
// es5
function f() { console.log('I am outside!'); }
(function () {
if (false) {
// 重复声明一次函数f
function f() { console.log('I am inside!'); }
}
f();
}());
// print I am inside!
// es6
// print TypeError
上述代码在es6中的真正解析方式为如下代码
// 浏览器的 ES6 环境
function f() { console.log('I am outside!'); }
(function () {
// 把函数提升为 var 变量
var f = undefined;
if (false) {
function f() { console.log('I am inside!'); }
}
f();
}());
本文用于本人知识记录与复习,借鉴原文为阮一峰的 ES6 入门教程
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。