学习ES6,主要是通过阮一峰大神的ECMAScript 6 入门(电子版+实体书)以及网络上的学习ES6的视频进行学习。为了更好的理解ES6的新特性以及记住其功能,用博客来梳理自己的学习过程以及思路。
1. var
的一些问题
在ES5及之前的ECMAScript中,变量声明的唯一方法就是使用var
,但var
的一些特性或者说ES
本身的缺陷容易让代码出现问题。
变量声明提升以及重复声明
变量声明提升是指 不管变量在何时声明,都将提升到作用域顶端
例如:
console.log(b) // undefined
var b = 2;
console.log(b) // 2
这样导致的结果就是,我们在某些时候在声明变量前使用变量也不会报错,这会给程序带来未知的问题。
重复声明是指
var
声明的变量可以进行第二次声明,第一次声明是变量,第二次声明变量(函数)将覆盖第一次变量
例如:
var a = 10;
console.log(a); // => 10
var a = 12;
console.log(a); // => 12
这样重复声明会导致我们第一次声明的变量被覆盖,而且不会有任何提示。比如当我们引入其他库变量时,却声明了变量将引入值覆盖了,那程序必然就出问题了。
作用域问题
ECMAScript
是只有函数作用域以及全局作用域的,这在使用中带来很多不遍
function test() {
if (true) {
var a = 10;
}
console.log(a)
}
test() //=> 10
这里原本是想当条件为true时才声明a变量以及赋值为10,但由于没有块级作用域,导致我们的这个需求不能被满足。
其实我们经常遇见的一道闭包面试题也是因为没有块级作用域造成的
for (var i = 0; i< 5;i++) {
setTimeout(function(){
console.log(i)
},1000)
}
// 5
// 5
// 5
// 5
// 5
因为没有块级作用域所以,当setTimeout
开始运行function
时,这个时候的作用域已经是全局作用域了,全局作用域下i
值已经变成5
2. let声明变量
let
声明变量的出现是为了解决上述var
存在的一些问题
变量声明不再提升
console.log(b) // => Uncaught ReferenceError: b is not defined
let b = 2;
当我们在变量声明之前使用变量时会直接报错b is not defined
,这可以让我们不必担心当前的变量还未声明
不能重复声明
function test(){
let b = 2;
console.log(b)
let b = 3;
console.log(b)
}
test() //=> `Identifier 'b' has already been declared`
重复声明变量也将导致浏览器报错
将自动生成块级作用域
function test() {
if(true) {
let a = 10;
}
console.log(a);
}
test() //=> Uncaught ReferenceError: a is not defined
使用let
进行变量声明时,会形成{}这样的块级作用域,所以不能再作用域外获取a
3. const声明常量
使用
const
声明不需要改变值的常量
const
声明的常量也有上述let
声明的特性
function test() {
const a =10;
a = 20;
console.log(a)
}
test() //=> Uncaught TypeError: Assignment to constant variable.
尝试改变const
声明的常量值的时候会报错
特别注意的是,
const
声明的常量不可改变,所以不能只声明不赋值,不然会导致再也不能赋值
function test() {
const a;
a = 20;
console.log(a)
}
test() //=> Uncaught TypeError: Assignment to constant variable.
要注意的
const
声明常量不可改变值,但对象可以添加值
function test() {
const obj = {};
obj.a = 'aaa'
console.log(obj)
}
test() //=> {a: "aaa"}
对象添加键值后并未报错,这是因为对象添加键值并未改变它在堆中的位置,所以其实const所表示的是地址不可变
全局对象的属性(全局变量)
在全局作用域下使用
var
声明的变量都属于全局变量,这样很容易不知不觉就创建了全局变量,所以ES6 规定var
和function
命令声明的全局变量依旧是全局对象的属性,但let``const
和class
声明的全局变量不再是全局对象的属性
let a = 1;
var b = 2;
console.log(window.a); // => undefined
console.log(window.b); // => 2
上面代码中全局变量a
由let
创建,所以不是全局对象的属性,返回undefined
,而b
是由var
创建,所以是全局对象的属性。