ES6的平常一些功能

一、前注

关于es6的详细说明,能够参照个人系列文章es6 从入门到熟练,或者阮一峰的ECMAScript 6 入门javascript

个人系列文章,是在阮一峰的基础上,增长了更多适合初中级开发者的内容(包括大量的示例代码和解释),以下降学习难度,丰富说明。html

本文是对es6总体的回顾,结合个人实际开发经验,对es6的一个小结。前端

为了精炼内容,es6里不经常使用的内容已经去掉,而对经常使用、重要的es6知识,附上简单的代码说明,并另附有详细说明的博文连接,方便初中级开发者理解。vue

二、开发环境

关键字:IE九、Babel、Babel的垫片、脚手架java

首先,使用es6的前提是最低IE9,若是你须要兼容IE8,建议放弃es6,专心使用神器jQuery。node

其次,若是须要使用es6来编写,那么你须要Babel转码器用于将你的es6代码转换为es5代码,用于兼容只能使用es5的环境。不然对于只能运行es5的环境(例如IE9),是没法运行es6代码的。git

第三,因为Babel在默认状况下,并非所有转换的,如如下说明:es6

Babel 默认只转换新的 JavaScript 句法(syntax),而不转换新的 API,好比Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise等全局对象,以及一些定义在全局对象上的方法(好比Object.assign)都不会转码。github

所以,咱们须要垫片,通常状况下能够用babel-polyfill,也能够用babel-runtime,这两个有所差别。web

babel-polyfill会污染全局对象,即会对例如Object这样的对象添加方法,而babel-runtime只会转换es6语法的代码,但若是你须要调用Object.assign这样的方法,那就不行了。

因为细节不少,所以这里给几个参考连接吧:

Babel 全家桶

babel的polyfill和runtime的区别

看完以上两个,可能会以为应该同时使用这两个,然而并不须要,看下面这个连接:

transform-runtime 会自动应用 polyfill,即使没有使用 babel-polyfillconanliu17 Dec 2016提交的issues。

若是你使用的Vue.js,那么能够直接fork个人脚手架,而后当作本身的脚手架使用。

附脚手架连接:vue-scaffold,若是能够,给个star喔~~

若是你用的不是Vue.js,那么能够去搜一下你所使用的框架的脚手架,而后拿来使用。若是找不到,能够找使用带脚手架的该框架项目,而后down下来,删除对方的项目只取壳来用便可。(若是有许可,记得阅读一下许可看能不能这么干)

三、let和const

既然有let和const了,那么推荐优先使用这两个。

通常状况下,let能够直接替代var,对于常量,能够用const。

这不是必须的,但用这2个能够帮你规范写代码的习惯,因此仍是强烈推荐的。

比较蛋疼的是,用webtorm,let有时候不会高亮,只有var和const是高亮的。这个多是用的风格的问题,我也不太肯定。解决方案我本身是没找到,凑合用吧。

另外,let和var之间的一个重要区别是变量提高,因此若是你写代码不太规范的话,可能会报错,好好检查一下吧。

另外,阮一峰推荐将函数设置为常量,就像这样子:

const add = function (a, b) { return a + b }
  • 1
  • 2
  • 3

我以为挺有道理的,推荐。

四、字符串

既然用es6,固然要用反引号这个高大上的东西了。

详细用法推荐我本身的博客:ECMAScript 6(7)模板字符串

最基本的用法,能够直接用反引号替代普通的引号(单引号和双引号)

例如:

let a = 'ab' // 能够直接用如下替换 let a = `ab`
  • 1
  • 2
  • 3

并且通常状况下,简单需求不用再拼接字符串了~(另外,反引号也能够像普通字符串那样拼接)

如:

let str = '20004604'; let html = 'my QQ is ' + str; //用如下替换 let str = '20004604'; let html = `my QQ is ${str}`;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

简单暴力省事。

五、解构赋值

最大的好处是简化了写法,如代码:

let obj = { a: 1, b: 2 } //old let a = obj.a; let b = obj.b; // es6 let {a, b} = obj
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

除了对象以外,还有数组也能够解构赋值,别忘了。

六、对象

es6的对象,比早期版本的写起来舒服不少。

例如:

  1. 对象属性是函数的时候能够简写;
  2. setter和getter的简写;
  3. 经过Object.assign()来合并对象,实现继承或添加属性效果;
  4. 能够用属性名表达式;
  5. 能够用变量名只要做为对象的属性名,而且变量的值能够自动成为对象该属性名的值;

列一些常见写法:

let obj = { // 对象属性是函数的时候能够简写 a(){ console.log('对象属性是函数的时候能够简写') }, // setter和getter的简写; get b() { return this._b }, set b(val) { this._b = val } } let c = '添加了一个c' // 经过``Object.assign()``来合并对象,实现继承或添加属性效果 // 能够用变量名只要做为对象的属性名,而且变量的值能够自动成为对象该属性名的值 Object.assign(obj, { c }) // 能够用属性名表达式 let d = "abcd" obj[d.replace(/abc/, '')] = '属性名表达式'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

七、数组

最经常使用的就两个:

  1. 扩展运算符...
  2. 将类数组的转为数组的Array.from()

如代码:

function getArgs() { let foo = [...arguments] console.log(foo) let bar = Array.from(arguments) console.log(bar) } getArgs(1, 2, 3) // [1, 2, 3] // [1, 2, 3]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

须要注意的一个特性:

  1. es5在面对,经过Array(5)这样生成带空位的数组时,处理他的时候会跳过空位数组的空位
  2. es6在一样状况下,由于使用遍历器接口,因此会进行处理(视为undefined),而不是跳过;

八、函数

函数经常使用特性有如下几个:

  1. 箭头函数:特色是this永远指向声明时的父级做用域,写起来比普通函数简单;
  2. bind:能够给函数绑定this,并将这个绑定后的函数返回(不影响原函数);
  3. rest函数:即函数参数使用例如function test(..args){}这样的,这个返回的是一个数组,而不是类数组。
  4. 参数默认值:通常带默认值的参数,放在参数列表的后面。
function test(a, b = 3) { console.log(a, b) console.log(this) } test.bind('Is this')(1) // 1 3 // Is this function test2(...args) { console.log(args.length) } test2(1, 2, 3, 4, 5) // 5
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

九、Set和Map

Set结构最大的特色是去重,Map结构最大的特色是kv结构。

Set:

Set和数组相似,能够存储元素,可是Set不能存储相同的值。

非引用类型变量来讲,就是值相等;对于引用类型变量来讲,指地址相等(而不是值相等)。详细状况请点击Set类型和WeakSet查看。

至于去重,通常是对数组使用。先做为参数生成一个Set类型变量,再利用扩展运算符变回数组,去重完成,完美。

利用扩展运算符,调用Set的迭代器接口

// 去重 let foo = new Set([1, 2, 3, 3, 3]) console.log([...foo]); // [1, 2, 3]
  • 1
  • 2
  • 3

Map:

Map结构和对象很是相似,不过最大的区别在于,Map结构能够用其余类型做为key,例如数组、对象等。

Map能够参照这篇博客Map和WeakMap

示例代码:

let zhang = { firstName: "王" } let property = { gender: "男" } let foo = new Map() foo.set(zhang, property) foo.has(zhang) // true foo.get(zhang) // {gender: "男"}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

十、Promise

Promise是es6的精华之一,他很是适用于异步处理。

Promise对象在使用的时候,分为两部分,第一部分是new Promise这一步,第二部分是对返回的Promise实例进行处理的内容。

由于是经过执行resolvereject来改变Promise的状态,从而决定执行then的时机的(相似回调函数),以及执行的哪个。所以写起来和回调函数相近,可是能够连写,避免回调地狱的状况。

关于Promise的详细介绍请阅读Promise(1)基础知识及以后三篇博客

如示例代码(对比普通ajax和promise)(另注:为了方便理解,仿jQuery的写法,而且没有用jQuery的$.ajax().then()这种写法)

// 模拟ajax function ajax (options) { setTimeout(function () { options.success(options.url) }, 1000) } // old let foo = function (callback) { ajax({ url: "/1", success: function (result) { callback(result) } }) } let foo2 = function (result) { console.log(result) return function (callback) { ajax({ url: "/2", success: function (val) { callback(val) } }) } } // 核心,调用的时候若是是连续请求的话,基本要写成回调地狱了 foo(function (result) { foo2(result)(function (val) { console.log(val) }) }) // Promise let bar = function () { return new Promise((resolve, reject) => { ajax({ url: "/1", success: function (result) { resolve(result) } }) }) } let bar2 = function (result) { console.log(result) return new Promise((resolve, reject) => { ajax({ url: "/2", success: function (val) { resolve(val) } }) }) } // 核心,then连写便可 bar().then(function (result) { return bar2(result) }).then(function (result) { console.log(result) })
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

显然,then连写比回调函数的写法要方便一些。

若是面对的是特殊需求,好比是多个ajax请求所有完成后,再执行执行函数,那么Promise的优点会更大一些,而非Promise写法要麻烦不少。

甚至若是要对错误进行处理,那么Promise写法会更方便。

不过这里只是小结,就不细说了。

十一、class

class是好东西。

有了class后,写构造函数、写类的继承的难度,降低了不少不少。

先附个人博文class(1)基本概念,以及以后5篇博文。

因为很简单,给一个示例大约就能理解这个是怎么用的:

class Foo { constructor () { console.log('this is constructor') this.defaultValue = '变量要在构造函数里赋值,而不能直接声明' } log () { console.log('log') } } let foo = new Foo() // this is constructor foo.log() // log foo.defaultValue // "变量要在构造函数里赋值,而不能直接声明"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

十二、es6模块

es6的模块不一样于以往的CommonJS(node用,服务器环境),AMD(RequireJS的规范,浏览器环境,依赖前置)、CMD(SeaJS定义的规范,浏览器环境,依赖就近)。

他的特色有两个:

  1. 编译时加载,所以能够作静态优化;
  2. 模块的引用进来的,都是值的引用,而非值的拷贝。

缺点是:

  1. 浏览器环境下不支持,node环境下支持的也比较差;
  2. 必须考babel转码后才能够正常使用,所以对某些符合规范的特性支持的不是很好;

详细说明阅读这篇博客:es6的import和export,另外三个规范阅读这篇博客AMD、CMD、CommonJS

基本使用方式如示例代码:

// foo.js let foo = 'foo' export default foo // bar.js import foo from 'foo' console.log(foo)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

1三、async函数

这个并非es6的,而是es2017(又称es8)的内容。

能够认为async函数是Generator函数的语法糖,详细说明参照这篇博客:async函数

他的前置知识比较多,包括Iterator遍历器、Generator状态机、Thunk函数(自动执行Generator 函数)。

简单的说,假若有多个异步请求,你须要让这些起步请求依次执行,例如在执行完前一个以后,再执行后一个。那么你就须要async函数了。

async函数可让你写这种请求如同写同步函数同样简单(对比【10】中的Promise更简单)。

如下示例是基于【10】中的代码,在最后一步执行的时候,改用async函数来完成

// 模拟ajax function ajax (options) { setTimeout(function () { options.success(options.url) }, 1000) } // Promise let bar = function () { return new Promise((resolve, reject) => { ajax({ url: "/1", success: function (result) { resolve(result) } }) }) } let bar2 = function (result) { console.log(result) return new Promise((resolve, reject) => { ajax({ url: "/2", success: function (val) { resolve(val) } }) }) } async function foo () { let result1 = await bar() let result2 = await bar2(result1) return result2 } foo().then(result => { console.log(result) })
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

能够发现,async让连续异步调用像写同步函数同样简单。

1四、ESLint

规范化开发,建议仍是用ESLint来帮忙检查吧。不会这个怎么行?

ESLint是一个语法规则和代码风格的检查工具,能够用来保证写出语法正确、风格统一的代码。

这里直接给一个阮一峰写的文章,等之后我再单独补一篇详细用法的博客。

ESLint的使用

1五、小结

es6经常使用内容基本就以上13点。

虽然es6实际包括了不少知识,例如:

  1. string方面增长了对utf16字符的更好的支持;
  2. number方面增长了对最大值、最小值、以及合理偏差偏差值的处理等;
  3. Symbol产生惟一变量;
  4. Proxy的代理;
  5. 遍历器,状态机等等。

但实际经常使用的就以上这些,若是只是平常使用的话,熟悉以上内容足够了。

但若要作的更好,那么应该深刻学习,es6新增的不少内容,是将传统后端语言的一些很好的思想,搬到JavaScript来,让js规范化。

对于专精于前端的同窗,学习es6的过程当中,能够学习到这些来自于其余语言的精华,所以建议至少完整的看一遍,勿要只知足于经常使用的这些API。

相关文章
相关标签/搜索