ES6新增特性


let关键字

作用域绑定在最近的{…}块中

let在使用时会绑定离它最近的{…}作为作用域。原本在ES6以前是没有块级作用域的概念,在ES6引入了let、const关键字之后就有了块级作用域。实际上这个块级作用域并不是我们平常理解的块级作用域,仅当变量是由let、const关键字声明时,这些关键字声明的变量其作用域会绑定在这个块上,若是使用var关键字声明,其变量依然会成为全局变量。

使用这个特性我们可以很好的解决 for 循环全局变量污染的问题

if(true){
	{
		let a = 10;
		var b = 20;
		console.log(a); // 10
	}
	console.log(a); // ReferenceError
}
console.log(b); // 20

无变量提升

let关键字在使用的时候,不像var那样存在变量提升的情况。它必须先声明再使用。

function fn(){
	console.log(a); // undefined
	console.log(b); //ReferenceError
	var a = 10;
	let b = 20;
}
fn();
//上述代码等价于
function fn(){
	var a;  //var变量提升至所在作用域顶部
	console.log(a); // undefined
	console.log(b); //ReferenceError
	a = 10;
	let b = 20;
}
fn();

暂时性死区

所谓暂时性死区就是,你在块级作用域使用let声明了一个变量i,同时你在外部作用域也声明的一个同名变量i。若你在let声明这个变量前使用它,它并不会像以前的那样去上级作用域寻找这个变量,仅会在该作用域内寻找变量,又因为变量使用let声明,并且声明在其使用之后,就会抛出ReferenceError。因为使用let在作用域内声明了同名变量,它会屏蔽外界变量,这个块级区域就被称为暂时性死区

var a = 20;
//if{}内形成暂时性死区
if(true){
	console.log(a); // ReferenceError
	let a = 10;
}
-------------
var b = 20;
//不是同名变量,没有暂时性死区
if(true){
	console.log(b); // 20
	let a = 10;
}

const

声明时必须赋值

const关键字的特性和let相同,let有的特性const都具有。不同点是它在声明的同时必须赋予一个值,否则抛出SyntaxError。

const a;  // SyntaxError

赋值后不可改变

这里const关键字声明的变量能否更改还需要看具体的情况。

const声明的是一个基本数据类型,则不能更改其值

const a = 10;
a = 20; // TypeError

但是如果const声明的是一个复杂数据类型,则可以更改复杂数据类型变量内部的值,不可更改该复杂数据类型变量本身

const b = [1,2,3];
b[1] = 100; 
console.log(b); // [1,100,3]
b = [3,4,5]; //TypeError

箭头函数

最初使用箭头函数的目的就是为了简化函数声明的操作,但它的作用不仅如此。我们都知道this指针的指向在不同地方其指向不同,例如在构造函数中其指向就是它的实例化对象,在class中的constructor中也是同样的指向自身的实例化对象,而在普通函数中其指向的是函数的调用者。

箭头函数中的this是根据上下文环境确定的

箭头函数this指向的是被声明的作用域里面

let btn = document.querSelector('.btn');
btn.onclick = function(){
	setTimeout(function(){
		console.log(this); // window
	},1000);
}
------------
//在定时器的回调函数中使用箭头函数则其this会根据上下文指向btn对象,而不是指向window
btn.onclick = function(){
	setTimeout(()=>{
		console.log(this); // btn
	},1000);
}

多种简写形式

当形参只有一个且函数体内仅有一句返回值时

let sum = n => n*3;

//等价一
let sum = (n) => {
    return n*3;
}
//等价二
let sum = function(n){
    return n*3;
}

函数体中只有一句代码,且代码的执行结果就是返回值,可以省略大括号

let sum = (a,b) => a+b;

//等价一
let sum = (a,b) => {
	return a + b;
}
//等价二
let sum = function(a,b){
    return a + b;
}

解构

数组的解构

在es6中我们可以使用新的方式来命名多个变量,这种新的声明赋值方式就叫解构

//传统命名多个变量并赋值的方式
let a = 10,b = 20,c = 30;

//采用数组解构的方式
let arr = [10,20,30];
let [a,b,c] = arr;  //a = 10,b = 20,c = 30

//当变量数量大于数组长度
let arr = [1,2,3];
let [a,b,c,d] = arr; //a = 1,b = 2, c = 3,d = undefined //多余的变量为未定义

//当变量数量少于数组长度
let arr = [1,2,3];
let [a,b] = arr; //a = 1,b = 2  //多余的直接被截断

--------------
//对象解构
let obj = {
    name:'Asuhe',
    age: 18,
    sex: '男'
}
let {name:myname,age:myage,sex:mysex} = obj; //myname = 'Asuhe',myage = 18,mysex = '男' //按匹配相同名称,即使乱序也会匹配上
//等价于
let myname = 'Asuhe';
let myage = 18;
let sex = '男';

----------------
let {name,age,sex} = obj;

等价于
let name = 'Asuhe';
let age = 18;
let sex = '男';

剩余参数

在es6中新扩展了一种方法可以使函数的形参接收不定数量的实参,那就是使用剩余参数。我们知道在以前js同样支持函数形参和实参数量不匹配,即使定义函数时形参列表为空我们依然可以使用arguments对象获取到实参。但在es6新增的箭头函数中并不支持arguments,所以es6扩展了...args剩余参数来解决这个问题。

//传统获取所有形参
function foo(){
	console.log(arguments[0]); //1
    console.log(arguments[1]); //2
    console.log(arguments[2]); //3
}
foo(1,2,3);

//使用剩余参数
function foo(a,...args){ //剩余参数必须放在最后一个形参的位置
    console.log(a); //1
    console.log(args); //[2,3,4,5] //以数组的形式存储值
}
foo(1,2,3,4,5);