ES6中比较实用的八个特性:
1.块级作用域的let和const
2.箭头函数
3.默认参数
4.模版表达式
5.多行字符串
6.Promise
7.类
8.模块化
1. 块级作用域的let和const
let是一个更新的var,可以让你把变量作用域限制在当前块里。我们用{}来定义块,但是在ES5中这些花括号起不到任何作用。
function test (e) {
var num = 0
if (e) {
var num = 1
}
{ // 更多的块
var num = 10
{
var num = 100
}
}
return num
}
console.log(test(true))
运行结果将会是100,简直变态···
在ES6中,我们用let来限制变量作用域为函数内。
function test (e) {
let num = 0
if (e) {
let num = 1
}
{ // 更多的块
let num = 10
{
let num = 100
}
}
return num
}
console.log(test(true))
运行结果是0。
说到const,就简单多了。他仅仅产生是一个不可变的变量,并且他的作用域也像let一样只有块级。为了演示,这里有定义了一堆常量,并且由于作用域的原因,这些定义都是有效的。
function test(e) {
const num = 0
if (e) {
const num = 1
}
{ // 更多的块
const num = 10
{
const num = 100
}
}
return num
}
console.log(test(true))
let和const让这门语言变得更加复杂,没有这些的时候我们只有一条路可以走,但是现在可以要考虑更多的情景。
2. ES6中的箭头函数
这些箭头最神奇的地方在于他会让你写正确的代码。比如,this
在上下文和函数中的值应当是相同的,它不会变化,通常变化的原因都是因为你创建了闭包。
使用箭头函数可以让我们不再用that = this
或者self = this
或者_this = this
或者.bind(this)
这样的代码,比如,这些代码在ES5中就特别丑。
var _this = this
$('.btn').click(function(event){
_this.sendData()
})
这是在ES6中去掉_this = this
之后:
$('.btn').click((event) =>{
this.sendData()
})
注意,在ES6中你可以合理的把箭头函数和旧式 function 函数混用。当箭头函数所在语句只有一行时,它就会变成一个表达式,它会直接返回这个语句的值。但是如果你有多行语句,你就要明确的使用return。
3. ES6中的默认参数
以前我们要这样子来定义默认参数:
var link = function (height, color, url) {
var height = height || 100
var color = color || 'skyblue'
var url = url || 'http://baidu.com'
...
}
在ES6中,我们可以把这些默认值直接放在函数签名中。
var link = function(height = 100, color = 'skyblue', url = 'http://baidu.com') {
...
}
4. ES6中的模版表达式
在ES5中,我们非得把字符串破开变成这样:
var name = 'Your name is ' + first + ' ' + last + '.'
var url = 'http://localhost:3000/api/messages/' + id
在ES6中我们有了新语法,在反引号包裹的字符串中,使用${name}语法来表示模板字符:
var name = `Your name is ${first} ${last}`
var url = `http://localhost:3000/api/messages/${id}`
5. ES6中的多行字符串
在ES5中想要实现多行字符串我们需要这样:
var roadPoem = 'Then took the other, as just as fair,nt'
+ 'And having perhaps the better claimnt'
+ 'Because it was grassy and wanted wear,nt'
+ 'Though as for that the passing therent'
+ 'Had worn them really about the same,nt'
var fourAgreements = 'You have the right to be you.n
You can only be you when you do your best.'
但是在ES6中,只要充分利用反引号。
var roadPoem = `Then took the other, as just as fair,
And having perhaps the better claim
Because it was grassy and wanted wear,
Though as for that the passing there
Had worn them really about the same,`
var fourAgreements = `You have the right to be you.
You can only be you when you do your best.`
6. ES6中的Promise
在ES6中有一个标准的Promise实现,可以解决嵌套过深的问题。
举一个延迟异步执行,用setTimeout实现:
setTimeout(function(){
console.log('Hi!')
}, 1000)
我们可以用ES6中的Promise重写:
var wait1000 = new Promise(function(resolve, reject) {
setTimeout(resolve, 1000)
}).then(function() {
console.log('Hi!')
})
或者用ES6的箭头函数:
var wait1000 = new Promise((resolve, reject)=> {
setTimeout(resolve, 1000)
}).then(()=> {
console.log('Hi!')
})
到现在为止,我们只是单纯增加了代码的行数,还明显没有带来任何好处。但是如果我们有更多复杂的逻辑内嵌在setTimeout()
中的回调时好处就来了:
setTimeout(function(){
console.log('Yay!')
setTimeout(function(){
console.log('Wheeyee!')
}, 1000)
}, 1000)
可以用ES6中的Promise重写:
var wait1000 = ()=> new Promise((resolve, reject)=> {setTimeout(resolve, 1000)})
wait1000()
.then(function() {
console.log('Yay!')
return wait1000()
})
.then(function() {
console.log('Wheeyee!')
});
7. ES6中的类
在ES5中,因为没有class关键字(但它是毫无作用的保留字),类的创建和使用十分麻烦。ES6的类会用prototype来实现而不是function。现在有一个baseModel类,其中我们可以定义构造函数和getName()
方法。
class baseModel {
constructor(options = {}, data = []) { // class 属性
this.name = 'Base'
this.url = 'http://baidu.com'
this.data = data
this.options = options
}
getName() { // class 方法
console.log(`Class name: ${this.name}`)
}
}
options和data用了默认参数,
而且方法名再也不用加上function。
8. ES6中的模块化
ES6之前JavaScript并没有对模块化有过原生的支持,于是有人创造出AMD(RequireJS),CommenJS等等,现在终于有import和export运算符来实现了。
ES5中你会用script标签和IIFE(立即执行函数),或者是其他的像AMD之类的库,但是ES6中你可以用export来暴露你的类。然后用Browserfy来浏览器化。
比如我们有一个port变量和getAccounts方法,在ES5中需要这么实现:
module.exports = {
port: 3000,
getAccounts: function() {
...
}
}
在ES5的main.js中,用require('模块')来导入:
var service = require('module.js')
console.log(service.port) // 3000
但是在ES6中,我们用export和import。比如这是ES6中的module.js文件:
export var port = 3000
export function getAccounts(url) {
...
}
在需要引入的main.js文件中,可以用import {名称} from '模块'语法:
import {port, getAccounts} from 'module'
console.log(port) // 3000
或者就直接在main.js
中引入所有的变量:
import * as service from 'module'
console.log(service.port) // 3000
由于现在的大部分浏览器还不支持ES6,,如果想马上就用上ES6,我们需要一个像Babel这样的编译器。你可以把他当独立工具用,也可以将他集成到构建系统里,Babel对Gulp,Grunt和Webpack都有对应的插件。
安装Gulp插件示例:
$ npm install --save-dev gulp-babel
在gulpfile.js中,定义这么一个任务,将src目录下的app.js文件编译到build目录下:
var gulp = require('gulp'),
babel = require('gulp-babel')
gulp.task('build', function () {
return gulp.src('src/app.js')
.pipe(babel())
.pipe(gulp.dest('build'))
})
Node.js和ES6
对于Node.js,你可以用构建工具或者直接用独立模块babel-core
:
$ npm install --save-dev babel-core
然后在Node.js中调用这个函数:
require('babel-core').transform(es5Code, options)
ES6的一些总结
ES6中还有很多比较不错的特性,如:
Math / Number / String/ Array/ Object中新的方法
二进制和八进制数据类型
自动展开多余参数
For of循环
Symbols
尾部调用优化generator
更新的数据结构(如Map和Set)
ES6相对于ES5的确是有比较大的优化,必然是未来发展的趋势所在,所以大家还是抓紧学习使用ES6吧。