ECMA:欧洲计算机制造联合会, 负责推动JavaScript改进,相当于对JavaScript的变更审批的组织。
最近通过ECMA发布的JavaScript版本是2015年6月获得批准,并被许多名称称为:ECMAScript 6,ES6,ES2015和ES6Harmony。
这章主要介绍ES6的一些新特性:
- 变量的声明:
1.const
常量,是一个无法更改的变量。 像之前的其他语言一样,JavaScript引入了ES6的常量。
以前:
var pizza = true
pizza = false
console.log(pizza) // false
现在:
const pizza = true
pizza = false
2.let
JavaScript现在有变量范围。
以前:
var topic = "JavaScript"
if (topic) {
var topic = "React"
console.log('block', topic) // block React
}
console.log('global', topic) // global React
现在:
var topic = "JavaScript"
if (topic) {
let topic = "React"
console.log('block', topic) // React
}
console.log('global', topic) // JavaScript
在for循环中变量范围:
以前:
var div, container = document.getElementById('container')
for (var i=0; i<5; i++) {
div = document.createElement('div')
div.onclick = function() {
alert('This is box #' + i)
}
container.appendChild(div)
}
现在:
var div, container = document.getElementById('container')
for (let i=0; i<5; i++) {
div = document.createElement('div')
div.onclick = function() {
alert('This is box #: ' + i)
}
container.appendChild(div)
}
3.模板字符串
模板字符串为我们提供了字符串连接的替代方法。 它们还允许我们将变量插入到字符串中。
以前:
console.log(lastName + ", " + firstName + " " + middleName)
现在:
console.log(`${lastName}, ${firstName} ${middleName}`)
在一个邮件模板中使用字符串模板
以前:
document.body.innerHTML = `
<section>
<header>
<h1>The HTML5 Blog</h1>
</header>
<article>
<h2>${article.title}</h2>
${article.body}
</article>
<footer>
<p>copyright ${new Date().getYear()} | The HTML5 Blog</p>
</footer>
</section>
现在:
`
Hello ${firstName},
Thanks for ordering ${qty} tickets to ${event}.
Order Details
${firstName} ${middleName} ${lastName}
${qty} x $${price} = $${qty*price} to ${event}
You can pick your tickets up at will call 30 minutes before
the show.
Thanks,
${ticketAgent}
`
4.缺省参数
function logActivity(name="Shane McConkey", activity="skiing") {
console.log( `${name} loves ${activity}` )
}
var defaultPerson = {
name: {
first: "Shane",
last: "McConkey"
},
favActivity: "skiing"
}
function logActivity(p=defaultPerson) {
console.log(`${p.name.first} loves ${p.favActivity}`)
}
- 箭头函数
使用箭头功能,您可以在不使用function关键字的情况下创建函数。 您通常也不必使用return关键字。
单行的函数:
以前:
var lordify = function(firstname) {
return `${firstname} of Canterbury`
}
console.log( lordify("Dale") ) // Dale of Canterbury
console.log( lordify("Daryle") ) // Daryle of Canterbury
现在:
var lordify = firstname => `${firstname} of Canterbury`
多行的行数:
以前:
var lordify = function(firstName, land) {
if (!firstName) {
throw new Error('A firstName is required to lordify')
}
if (!land) {
throw new Error('A lord must have a land')
}
return `${firstName} of ${land}`
}
现在:
var lordify = (firstName, land) => {
if (!firstName) {
throw new Error('A firstName is required to lordify')
}
if (!land) {
throw new Error('A lord must have a land')
}
return `${firstName} of ${land}`
}
箭头函数保护范围
以前:
var tahoe = {
resorts: ["Kirkwood","Squaw","Alpine","Heavenly","Northstar"],
print: function(delay=1000) {
setTimeout(function() {
console.log(this.resorts.join(", "))
}, delay)
}
}
tahoe.print() // Cannot read property 'join' of undefined
现在:
var tahoe = {
resorts: ["Kirkwood","Squaw","Alpine","Heavenly","Northstar"],
print: function(delay=1000) {
setTimeout(() => {
console.log(this.resorts.join(", "))
}, delay)
}
}
tahoe.print() // Kirkwood, Squaw, Alpine, Heavenly, Northstar
注意箭头函数变量范围:
var tahoe = {
resorts: ["Kirkwood","Squaw","Alpine","Heavenly","Northstar"],
print: (delay=1000) => {
setTimeout(() => {
console.log(this.resorts.join(","))
}, delay)
}
}
tahoe.print() // Cannot read property resorts of undefined
var tahoe = {
resorts: ["Kirkwood","Squaw","Alpine","Heavenly","Northstar"],
print: (delay=1000)=> {
setTimeout(() => {
console.log(this === window)
}, delay)
}
}
tahoe.print()
var tahoe = {
resorts: ["Kirkwood","Squaw","Alpine","Heavenly","Northstar"],
print: function(delay=1000) {
setTimeout(() => {
console.log(this === window)
}, delay)
}
}
tahoe.print() // false
- Transpiling ES6
不是所有的浏览器都支持ES6,我们可以通过转换工具将ES6转换为ES5,最流行的转换工具是 Babel。
转换前:
const add = (x=5, y=10) => console.log(x+y);
转换后:
"use strict";
var add = function add() {
var x = arguments.length <= 0 || arguments[0] === undefined ?
5 : arguments[0];
var y = arguments.length <= 1 || arguments[1] === undefined ?
10 : arguments[1];
return console.log(x + y);
};
- ES6 对象和数组
1.解构赋值
var sandwich = {
bread: "dutch crunch",
meat: "tuna",
cheese: "swiss",
toppings: ["lettuce", "tomato", "mustard"]
}
var {bread, meat} = sandwich
console.log(bread, meat) // dutch crunch tuna
var {bread, meat} = sandwich
bread = "garlic"
meat = "turkey"
console.log(bread) // garlic
console.log(meat) // turkey
console.log(sandwich.bread, sandwich.meat) // dutch crunch tuna
函数中赋值:
var lordify = regularPerson => {
console.log(`${regularPerson.firstname} of Canterbury`)
}
var regularPerson = {
firstname: "Bill",
lastname: "Wilson"
}
lordify(regularPerson) // Bill of Canterbury
var lordify = ({firstname}) => {
console.log(`${firstname} of Canterbury`)
}
lordify(regularPerson) // Bill of Canterbury
var [firstResort] = ["Kirkwood", "Squaw", "Alpine"]
console.log(firstResort) // Kirkwood
var [,,thirdResort] = ["Kirkwood", "Squaw", "Alpine"]
console.log(thirdResort) // Alpine
2.对象文面量增强
var name = "Tallac"
var elevation = 9738
var funHike = {name,elevation}
console.log(funHike) // {name: "Tallac", elevation: 9738}
var name = "Tallac"
var elevation = 9738
var print = function() {
console.log(`Mt. ${this.name} is ${this.elevation} feet tall`)
}
var funHike = {name,elevation,print}
funHike.print() // Mt. Tallac is 9738 feet tall
定义对象方法时,不再需要使用function关键字:
以前:
var skier = {
name: name,
sound: sound,
powderYell: function() {
var yell = this.sound.toUpperCase()
console.log(`${yell} ${yell} ${yell}!!!`)
},
speed: function(mph) {
this.speed = mph
console.log('speed:', mph)
}
}
现在:
const skier = {
name,
sound,
powderYell() {
let yell = this.sound.toUpperCase()
console.log(`${yell} ${yell} ${yell}!!!`)
},
speed(mph) {
this.speed = mph
console.log('speed:', mph)
}
}
3.扩展运算符
扩展运算符是三个点(...),执行几个不同的任务:
合并数组:
var peaks = ["Tallac", "Ralston", "Rose"]
var canyons = ["Ward", "Blackwood"]
var tahoe = [...peaks, ...canyons]
console.log(tahoe.join(', ')) // Tallac, Ralston, Rose, Ward, Blackwood
创建一个数组的副本:
var peaks = ["Tallac", "Ralston", "Rose"]
var [last] = peaks.reverse()
console.log(last) // Rose
console.log(peaks.join(', ')) // Rose, Ralston, Tallac
var peaks = ["Tallac", "Ralston", "Rose"]
var [last] = [...peaks].reverse()
console.log(last) // Rose
console.log(peaks.join(', ')) // Tallac, Ralston, Rose
var lakes = ["Donner", "Marlette", "Fallen Leaf", "Cascade"]
var [first, ...rest] = lakes
console.log(rest.join(", ")) // "Marlette, Fallen Leaf, Cascade"
收集一个函数的多个参数:
function directions(...args) {
var [start, ...remaining] = args
var [finish, ...stops] = remaining.reverse()
console.log(`drive through ${args.length} towns`)
console.log(`start in ${start}`)
console.log(`the destination is ${finish}`)
console.log(`stopping ${stops.length} times in between`)
}
directions(
"Truckee",
"Tahoe City",
"Sunnyside",
"Homewood",
"Tahoma"
)
合并两个对象:
var morning = {
breakfast: "oatmeal",
lunch: "peanut butter and jelly"
}
var dinner = "mac and cheese"
var backpackingMeals = {
...morning,
dinner
}
console.log(backpackingMeals) // { breakfast: "oatmeal",
// lunch: "peanut butter and jelly",
// dinner: "mac and cheese"}
- Promises
const getFakeMembers = count => new Promise((resolves, rejects) => {
const api = `https://api.randomuser.me/?nat=US&results=${count}`
const request = new XMLHttpRequest()
request.open('GET', api)
request.onload = () =>
(request.status === 200) ?
resolves(JSON.parse(request.response).results) :
reject(Error(request.statusText))
request.onerror = (err) => rejects(err)
request.send()
})
getFakeMembers(5).then(
members => console.log(members),
err => console.error(
new Error("cannot load members from randomuser.me"))
)
- Classes
以前JavaScript是没有正式的类这种类型,类是用函数定义的。
以前:
function Vacation(destination, length) {
this.destination = destination
this.length = length
}
Vacation.prototype.print = function() {
console.log(this.destination + " | " + this.length + " days")
}
var maui = new Vacation("Maui", 7)
maui.print() // Maui | 7 days
现在:
class Vacation {
constructor(destination, length) {
this.destination = destination
this.length = length
}
print() {
console.log(`${this.destination} will take ${this.length} days.`)
}
}
const trip = new Vacation("Santiago, Chile", 7)
trip.print() // Chile will take 7 days.
类的继承:
class Expedition extends Vacation {
constructor(destination, length, gear) {
super(destination, length)
this.gear = gear
}
print() {
super.print()
console.log(`Bring your ${this.gear.join(" and your ")}`)
}
}
const trip = new Expedition("Mt. Whitney", 3,
["sunglasses", "prayer flags", "camera"])
trip.print()
// Mt. Whitney will take 3 days.
// Bring your sunglasses and your prayer flags and your camera
使用class关键字时候还是可以使用 Vacation.prototype查看类的属性。
- ES6 Modules
export const print(message) => log(message, new Date())
export const log(message, timestamp) =>
console.log(`${timestamp.toString()}: ${message}`)
const freel = new Expedition("Mt. Freel", 2, ["water", "snack"])
export default freel
import { print, log } from './text-helpers'
import freel from './mt-freel'
print('printing a message')
log('logging a message')
freel.print()
import { print as p, log as l } from './text-helpers'
p('printing a message')
l('logging a message')
导入所有函数:
import * as fns from './text-helpers
- CommonJS
CommonJS不支持import语句。 而是使用require函数导入模块。
const { log, print } = require('./txt-helpers')