块级作用域
es5只有全局作用域和函数作用域,没有块级作用域,这带来了很多不合理的场景。
第一种场景:内层变量可能会覆盖外层变量
var test = "outside";
function f () {
console.log(test);
if (false) {
var test = "inside";
}
}
f(); // undefined
出现这种结果的原因是变量提升,导致内层的test覆盖了外层的test
第二种场景:用来计数的循环变量泄露为全局变量
var str = "hello";
for(var i = 0; i < str.length; i++){
console.log(s[i]);
}
console.log(i); // 5
let命令
let声明的变量只在其代码块内有效,var没有块作用域
不存在变量提升
暂时性死区(TDZ):es6明确规定,如果区域块中存在let和const命令,则这个区块对这些命令声明的变量从一开始就形成封闭性作用域。只要在声明之前调用这些变量就会报错。
{
//TDZ开始
test = "test"; //ReferenceError
console.log(test); //ReferenceError
let test; //TDZ结束
console.log(test); //undefined
//比较隐蔽的TDZ
function testFn (x=y, y=2) {
return[x,y];
}
testFn(); //报错
}
不允许重复声明:不允许在同一个作用域内重复声明同一个变量
//报错
{
let test = 1;
var test = 2;
}
//报错
{
let test = 1;
let test = 2;
}
const
const用来声明常量
一旦声明,其值就不能改变
必须立即初始化,即立即赋值
不存在常量提升,同let一样存在暂时性死区
同let一样不可重复声明
作用域:只在当前代码块有效
const命令只能保证常量名指向数据的地址不变,但是不能保证该地址的数据不变,如
const obj = {};
obj.prop = 'test';
console.log(obj.prop); //'test'
obj = {}; //typeError: "obj" is read-only
跨模块常量
可使用export使常量跨模块
//constant.js
export const A = 1;
export const A = 2;
export const A = 3;
//test1模块
import * as constants from './constans';
console.log(constants.A); // 1
console.log(constants.B); // 2
//test1模块
import {A, B} from './constans';
console.log(constants.A); // 1
console.log(constants.B); // 2
全局对象的属性
在es5中,全局对象(window/global)的属性与全局变量是等价,在es6中规定,let、const、class命令生声明的全局变量不属于全局对象的属性。如
var a = 1;
b = 2;
console.log(window.a); // 1
console.log(window.b); // 2
let c = 3;
console.log(window.c); // undefined
es6声明变量的方法
es5只有两种声明变量的方法:var、function命令
es6一共有六种:var、function、let、const、import、class命令
变量的解构赋值
es6允许按照一定的模式,从数组和对象中提取,按照位置的对应关系对变量赋值,这被称为解构。本质上,这种写法属于模式匹配。
数组的解构赋值
//- 解构成功:等号两边模式相同
var [a, b, c] = [1, 2, 3];
console.log(a, b, c); // 1 2 3
let [l, [[m], n]] = [1, [[2], 3]];
console.log(l, m, n); // 1 2 3
let [x, , y] = [1, 2, 3];
console.log(x, y); // 1 3
let [o, ...p] = [1, 2, 3, 4];
console.log(o); // 1
console.log(p); // [2, 3, 4]
//- 不完全解构: 等号左边的模式只匹配等号右边数组的一部分
let [x, y] = [1, 2, 3];
console.log(x); //1
console.log(y); //2
let [x, [y], z] = [1, [2, 3], 4];
console.log(x); //1
console.log(y); //2
console.log(z); //4
//-解构不成功。如果解构不成功,变量的值就等于undefined
let [a, b, c] = [1];
console.log(a); //1
console.log(y); //undefined
console.log(z); //undefined
注意,如果等号的右边不是数组,严格来说不是遍历结构,那么将会报错
//-报错
let [a] = 1;
let [b] = false;
let [c] = NaN;
let [d] =undefined;
let [e] = null;
let [f] = {};
前5种转为对象后不具备iterator接口,最后一个本身就不具备iterator接口
事实上,只要某种数据接口具备iterator接口,都可以使用数组形式的解构赋值
默认值
明天再写
对象的解构赋值
字符串的解构赋值
数值和布尔值的解构赋值
函数参数的结构赋值
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。