ES6新特性速览

2018-2-5 分类: Web前端

引言

ES6引入了很多新的语言特性和能力,这篇文章仅快速地做一个概览。包括let、解构、箭头函数、模块化、Spread运算符 等。ES6还有很多更深入的内容,有时间再单独总结。大部分的ES6新特性,最新版的Chrome浏览器都原生支持,所以下面大多数代码不需要使用Babel转码器即可直接运行。但是模块化的import和export则暂未支持,只能通过Babel经过webpack等工具打包后使用。

let和var

let具有括号作用域,而var仅有函数作用域,没有括号作用域,因此在大多数情况下都推荐使用let。下面是简单的对比。

for(var i=0; i<3; i++){} console.log(i); // 3 for(let j=0; j<3; j++){} console.log(j); // Uncaught ReferenceError: j is not defined

使用var时,为了避免变量冲突,通常是使用立即执行函数来建立一个块级作用域:

(function(){ var i = 1; console.log("a:", i); // 1 })(); console.log("b:", i); // Uncaught ReferenceError: i is not defined

如果是代码块,变量在代码块结束后依然会存在:

{ var j = 1; console.log("a:", j); // 1 } console.log("b:", j); // 1

使用let则不会有这个问题:

{ let i = 1; console.log("a:", i); // 1 } console.log("b:", i); // Uncaught ReferenceError: i is not defined

一个典型的作用域问题是:遍历li对象,并赋予点击事件:

<ul> <li>项目A</li> <li>项目B</li> <li>项目C</li> </ul>

var arr = document.querySelectorAll("li"); for(var i=0; i<arr.length; i++){ arr[i].onclick = function(){ alert("你点击了第"+ i +"个项目"); } } console.log("i:", i); // 3

此时,不管点击哪个li,都会弹出“你点击了第3个项目”,因为在for循环结束后,i依然“活着”,并且值为3。

只需要将var i=0 改为 let i=0,则没有这个问题。而在let出现以前,传统的解决方案依然是利用函数作用域,将i作为立即执行函数的参数,写一个闭包函数:

var arr = document.querySelectorAll("li"); for(var i=0; i<arr.length; i++){ (function(x){ arr[x].onclick = function(){ alert("你点击了第"+ x +"个项目"); } })(i); }

const

服务端的很多语言都有const,例如我比较熟悉的C#,顾名思义,变量用const声明后值不可以再变。

const PI = 3.1415926; PI = 3; // Uncaught TypeError: Assignment to constant variable.

const还有两个注意事项,1:声明时就需要赋值。

const PI; // Uncaught SyntaxError: Missing initializer in const declaration PI = 3.1415926;

2:如果是对象,可以修改内部值,但不能重新赋值。

const loc = { x:1 , y: 2} loc.x = 3; console.log(loc); // {x:3, y:2} loc = {} // Uncaught TypeError: Assignment to constant variable.

箭头函数

箭头函数类似C#中的lambda表达式,大多数情况下,可以作为函数的简写形式。

function multiply(x){ return x*2; } // 相当于 const multiply = (x) => { return x*2; }

当函数体只有一行return时,可以再次简化,省略掉花括号和return关键字。

const multiply = (x) => x*2;

当只有一个输入参数时,参数的圆括号()也可以省略掉。(如果有多个参数或者没有参数,则必须有圆括号)。

const multiply = x => x*2; var i = multiply(1); console.log(i); // 2

箭头函数和普通函数最重要的一个区别,就是this关键字绑定到了函数定义时的作用域,而非函数运行时的作用域。下面是一个例子:

function Product(){ this.title = "NS Switch"; this.showName1 = function(){ console.log(this) console.log("showName1:", this.title); } this.showName2 = ()=>{ console.log(this) console.log("showName2:", this.title); } } var p = new Product(); var showName1 = p.showName1; var showName2 = p.showName2; showName1(); // Uncaught TypeError: Cannot read property 'title' of undefined showName2(); // NS Switch setTimeout(p.showName1, 1000) // this为window,this.title为undefined setTimeout(p.showName2, 1000) // NS Switch

import和export

import和export用于支持模块化(modules)。假设utility.js用来创建模块,而page.js使用该模块,则用法如下所示:

方式1:使用default关键字

// utility.js const Person = { name : "jimmy" } export default Person

// page.js import util from "./utility.js" console.log(util); // {name:"jimmy"}

方式2:多个对象时使用星号 *

// utility.js export const Person = { name : "jimmy" } export const Student = { score: 100 }

// page.js import * as util from "./utility.js" console.log(util.Person); // {name:"jimmy"} console.log(util.Student); // {score:100}

方式3:多个对象时使用析构

模块导出不变。模块引入才用下面的方式。

// page.js import { Person, Student } from "./utility.js" console.log(Person); // {name:"jimmy"} console.log(Student); // {score:100}

Spread和Rest运算符

这两个运算符的表示方法都是三个点:...,根据使用的位置来区分。

Spread运算符:用于展开数组或者对象。

// 数组展开 var oldArr = [1,2,3] var newArr = [0, ...oldArr, 4] console.log(newArr); // [0,1,2,3,4]

// 对象展开 var oldObj = { x:1, y:2} var newObj = { ...oldObj, z:3 } console.log(newObj); // {x: 1, y: 2, z: 3}

需要注意的是,当新对象的属性名重复时,会进行覆盖:

var oldObj = { x:1, y:2} var newObj = {...oldObj, y:3 } console.log(newObj); // {x: 1, y: 3}

Rest运算符:用于个数不定的函数参数

可以看到,实际上相当于将不定个数的函数参数合并成了数组。

function total(...args){ var t = 0; for(let i=0; i< args.length;i++){ t += args[i] } return t; } console.log(total(1,2)) // 3 console.log(total(3,4,5)) // 12

析构(destructering)

更方便地将数组元素或者对象属性提取出来保存到变量中。

// 析构数组 const arr = [1,2,3] var [x, y] = arr; console.log(x, y); // 1, 2 var [, , z] = arr; console.log(z); // 3

// 析构对象 const obj = { x:1, y:2, z:3 } var {x, z} = obj; console.log(x, z); // 1, 3

感谢阅读,希望这篇文章能给你带来帮助!