2018-2-5 作者: 张子阳 分类: Web前端
ES6引入了很多新的语言特性和能力,这篇文章仅快速地做一个概览。包括let、解构、箭头函数、模块化、Spread运算符 等。ES6还有很多更深入的内容,有时间再单独总结。大部分的ES6新特性,最新版的Chrome浏览器都原生支持,所以下面大多数代码不需要使用Babel转码器即可直接运行。但是模块化的import和export则暂未支持,只能通过Babel经过webpack等工具打包后使用。
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,例如我比较熟悉的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用于支持模块化(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运算符:用于展开数组或者对象。
// 数组展开
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
更方便地将数组元素或者对象属性提取出来保存到变量中。
// 析构数组
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
感谢阅读,希望这篇文章能给你带来帮助!