We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
关于 es6 的详细说明,可以参照我的系列文章es6 从入门到熟练,或者阮一峰的ECMAScript 6 入门。
我的系列文章,是在阮一峰的基础上,增加了更多适合初中级开发者的内容(包括大量的示例代码和解释),以降低学习难度,丰富说明。
本文是对 es6 整体的回顾,结合我的实际开发经验,对 es6 的一个小结。
为了精炼内容,es6 里不常用的内容已经去掉,而对常用、重要的 es6 知识,附上简单的代码说明,并另附有详细说明的博文链接,方便初中级开发者理解。
关键字:IE9、Babel、Babel 的垫片、脚手架
首先,使用 es6 的前提是最低 IE9,如果你需要兼容 IE8,建议放弃 es6,专心使用神器 jQuery。
其次,如果需要使用 es6 来编写,那么你需要Babel转码器用于将你的 es6 代码转换为 es5 代码,用于兼容只能使用 es5 的环境。否则对于只能运行 es5 的环境(例如 IE9),是无法运行 es6 代码的。
Babel
第三,由于 Babel 在默认情况下,并不是全部转换的,如以下说明:
Babel 默认只转换新的 JavaScript 句法(syntax),而不转换新的 API,比如 Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局对象,以及一些定义在全局对象上的方法(比如 Object.assign)都不会转码。
因此,我们需要垫片,一般情况下可以用babel-polyfill,也可以用babel-runtime,这两个有所差异。
babel-runtime
babel-polyfill 会污染全局对象,即会对例如 Object 这样的对象添加方法,而 babel-runtime 只会转换 es6 语法的代码,但如果你需要调用 Object.assign 这样的方法,那就不行了。
由于细节很多,因此这里给几个参考链接吧:
Babel 全家桶
babel 的 polyfill 和 runtime 的区别
看完以上两个,可能会觉得应该同时使用这两个,然而并不需要,看下面这个链接:
transform-runtime 会自动应用 polyfill,即便没有使用 babel-polyfill的conanliu于17 Dec 2016提交的 issues。
conanliu
17 Dec 2016
如果你使用的 Vue.js,那么可以直接 fork 我的脚手架,然后当做自己的脚手架使用。
附脚手架链接:vue-scaffold,如果可以,给个 star 喔~~
如果你用的不是 Vue.js,那么可以去搜一下你所使用的框架的脚手架,然后拿来使用。如果找不到,可以找使用带脚手架的该框架项目,然后 down 下来,删除对方的项目只取壳来用即可。(如果有许可,记得阅读一下许可看能不能这么干)
既然有 let 和 const 了,那么推荐优先使用这两个。
一般情况下,let 可以直接替代 var,对于常量,可以用 const。
这不是必须的,但用这 2 个可以帮你规范写代码的习惯,所以还是强烈推荐的。
比较蛋疼的是,用 webtorm,let 有时候不会高亮,只有 var 和 const 是高亮的。这个可能是用的风格的问题,我也不太确定。解决方案我自己是没找到,凑合用吧。
另外,let 和 var 之间的一个重要区别是变量提升,所以如果你写代码不太规范的话,可能会报错,好好检查一下吧。
另外,阮一峰推荐将函数设置为常量,就像这样子:
const add = function (a, b) { return a + b } 复制代码
我觉得挺有道理的,推荐。
既然用 es6,当然要用反引号这个高大上的东西了。
详细用法推荐我自己的博客:ECMAScript 6(7)模板字符串
最基本的用法,可以直接用反引号替代普通的引号(单引号和双引号)
例如:
let a = 'ab' // 可以直接用以下替换 let a = `ab` 复制代码
而且一般情况下,简单需求不用再拼接字符串了~(另外,反引号也可以像普通字符串那样拼接)
如:
let str = '20004604'; let html = 'my QQ is ' + str; //用以下替换 let str = '20004604'; let html = `my QQ is ${str}`; 复制代码
简单暴力省事。
最大的好处是简化了写法,如代码:
let obj = { a: 1, b: 2 } //old let a = obj.a; let b = obj.b; // es6 let {a, b} = obj 复制代码
除了对象之外,还有数组也可以解构赋值,别忘了。
es6 的对象,比早期版本的写起来舒服很多。
Object.assign()
列一些常见写法:
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/, '')] = '属性名表达式' 复制代码
最常用的就两个:
...
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] 复制代码
需要注意的一个特性:
Array(5)
函数常用特性有以下几个:
箭头函数:特点是 this 永远指向声明时的父级作用域,写起来比普通函数简单;
bind:可以给函数绑定 this,并将这个绑定后的函数返回(不影响原函数);
rest 函数:即函数参数使用例如function test(..args){}这样的,这个返回的是一个数组,而不是类数组。
function test(..args){}
参数默认值:一般带默认值的参数,放在参数列表的后面。
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 复制代码
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] 复制代码
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: "男"} 复制代码
Promise 是 es6 的精华之一,他非常适用于异步处理。
Promise 对象在使用的时候,分为两部分,第一部分是new Promise这一步,第二部分是对返回的 Promise 实例进行处理的内容。
new Promise
因为是通过执行resolve或reject来改变 Promise 的状态,从而决定执行 then 的时机的(类似回调函数),以及执行的哪一个。因此写起来和回调函数相近,但是可以连写,避免回调地狱的情况。
resolve
reject
关于 Promise 的详细介绍请阅读Promise(1) 基础知识及之后三篇博客
如示例代码(对比普通 ajax 和 promise)(另注:为了方便理解,仿 jQuery 的写法,并且没有用 jQuery 的$.ajax().then()这种写法)
$.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) }) 复制代码
显然,then 连写比回调函数的写法要方便一些。
如果面对的是特殊需求,比如是多个 ajax 请求全部完成后,再执行执行函数,那么 Promise 的优势会更大一些,而非 Promise 写法要麻烦很多。
甚至如果要对错误进行处理,那么 Promise 写法会更方便。
不过这里只是小结,就不细说了。
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 // "变量要在构造函数里赋值,而不能直接声明" 复制代码
es6 的模块不同于以往的 CommonJS(node 用,服务器环境),AMD(RequireJS 的规范,浏览器环境,依赖前置)、CMD(SeaJS 定义的规范,浏览器环境,依赖就近)。
他的特点有两个:
缺点是:
详细说明阅读这篇博客:es6 的 import 和 export,另外三个规范阅读这篇博客AMD、CMD、CommonJS
基本使用方式如示例代码:
// foo.js let foo = 'foo' export default foo // bar.js import foo from 'foo' console.log(foo) 复制代码
这个并不是 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) }) 复制代码
可以发现,async 让连续异步调用像写同步函数一样简单。
规范化开发,建议还是用 ESLint 来帮忙检查吧。不会这个怎么行?
ESLint 是一个语法规则和代码风格的检查工具,可以用来保证写出语法正确、风格统一的代码。
这里直接给一个阮一峰写的文章,等以后我再单独补一篇详细用法的博客。
ESLint 的使用
es6 常用内容基本就以上 13 点。
虽然 es6 实际包括了很多知识,例如:
但实际常用的就以上这些,如果只是日常使用的话,熟悉以上内容足够了。
但若要做的更好,那么应该深入学习,es6 新增的很多内容,是将传统后端语言的一些很好的思想,搬到 JavaScript 来,让 js 规范化。
对于专精于前端的同学,学习 es6 的过程中,可以学习到这些来自于其他语言的精华,因此建议至少完整的看一遍,勿要只满足于常用的这些 API。
我的技术交流 QQ 群:387017550,感兴趣的欢迎加入和我进行讨论,群里有很多 BAT 的同学,也会解答常见问题。 https://juejin.im/post/5ee9a1556fb9a0586320a395?utm_source=gold_browser_extension
The text was updated successfully, but these errors were encountered:
No branches or pull requests
1、前注
关于 es6 的详细说明,可以参照我的系列文章es6 从入门到熟练,或者阮一峰的ECMAScript 6 入门。
我的系列文章,是在阮一峰的基础上,增加了更多适合初中级开发者的内容(包括大量的示例代码和解释),以降低学习难度,丰富说明。
本文是对 es6 整体的回顾,结合我的实际开发经验,对 es6 的一个小结。
为了精炼内容,es6 里不常用的内容已经去掉,而对常用、重要的 es6 知识,附上简单的代码说明,并另附有详细说明的博文链接,方便初中级开发者理解。
2、开发环境
关键字:IE9、Babel、Babel 的垫片、脚手架
首先,使用 es6 的前提是最低 IE9,如果你需要兼容 IE8,建议放弃 es6,专心使用神器 jQuery。
其次,如果需要使用 es6 来编写,那么你需要
Babel
转码器用于将你的 es6 代码转换为 es5 代码,用于兼容只能使用 es5 的环境。否则对于只能运行 es5 的环境(例如 IE9),是无法运行 es6 代码的。第三,由于 Babel 在默认情况下,并不是全部转换的,如以下说明:
因此,我们需要垫片,一般情况下可以用babel-polyfill,也可以用
babel-runtime
,这两个有所差异。babel-polyfill 会污染全局对象,即会对例如 Object 这样的对象添加方法,而 babel-runtime 只会转换 es6 语法的代码,但如果你需要调用 Object.assign 这样的方法,那就不行了。
由于细节很多,因此这里给几个参考链接吧:
Babel 全家桶
babel 的 polyfill 和 runtime 的区别
看完以上两个,可能会觉得应该同时使用这两个,然而并不需要,看下面这个链接:
transform-runtime 会自动应用 polyfill,即便没有使用 babel-polyfill的
conanliu
于17 Dec 2016
提交的 issues。如果你使用的 Vue.js,那么可以直接 fork 我的脚手架,然后当做自己的脚手架使用。
附脚手架链接:vue-scaffold,如果可以,给个 star 喔~~
如果你用的不是 Vue.js,那么可以去搜一下你所使用的框架的脚手架,然后拿来使用。如果找不到,可以找使用带脚手架的该框架项目,然后 down 下来,删除对方的项目只取壳来用即可。(如果有许可,记得阅读一下许可看能不能这么干)
3、let 和 const
既然有 let 和 const 了,那么推荐优先使用这两个。
一般情况下,let 可以直接替代 var,对于常量,可以用 const。
这不是必须的,但用这 2 个可以帮你规范写代码的习惯,所以还是强烈推荐的。
比较蛋疼的是,用 webtorm,let 有时候不会高亮,只有 var 和 const 是高亮的。这个可能是用的风格的问题,我也不太确定。解决方案我自己是没找到,凑合用吧。
另外,let 和 var 之间的一个重要区别是变量提升,所以如果你写代码不太规范的话,可能会报错,好好检查一下吧。
另外,阮一峰推荐将函数设置为常量,就像这样子:
我觉得挺有道理的,推荐。
4、字符串
既然用 es6,当然要用反引号这个高大上的东西了。
详细用法推荐我自己的博客:ECMAScript 6(7)模板字符串
最基本的用法,可以直接用反引号替代普通的引号(单引号和双引号)
例如:
而且一般情况下,简单需求不用再拼接字符串了~(另外,反引号也可以像普通字符串那样拼接)
如:
简单暴力省事。
5、解构赋值
最大的好处是简化了写法,如代码:
除了对象之外,还有数组也可以解构赋值,别忘了。
6、对象
es6 的对象,比早期版本的写起来舒服很多。
例如:
Object.assign()
来合并对象,实现继承或添加属性效果;列一些常见写法:
7、数组
最常用的就两个:
...
;Array.from()
如代码:
需要注意的一个特性:
Array(5)
这样生成带空位的数组时,处理他的时候会跳过空位数组的空位;8、函数
函数常用特性有以下几个:
箭头函数:特点是 this 永远指向声明时的父级作用域,写起来比普通函数简单;
bind:可以给函数绑定 this,并将这个绑定后的函数返回(不影响原函数);
rest 函数:即函数参数使用例如
function test(..args){}
这样的,这个返回的是一个数组,而不是类数组。参数默认值:一般带默认值的参数,放在参数列表的后面。
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
复制代码
9、Set 和 Map
Set 结构最大的特点是去重,Map 结构最大的特点是 kv 结构。
Set:
Set 和数组类似,可以存储元素,但是 Set 不能存储相同的值。
非引用类型变量来说,就是值相等;对于引用类型变量来说,指地址相等(而不是值相等)。详细情况请点击Set 类型和 WeakSet查看。
至于去重,一般是对数组使用。先作为参数生成一个 Set 类型变量,再利用扩展运算符变回数组,去重完成,完美。
利用扩展运算符,调用 Set 的迭代器接口
Map:
Map 结构和对象非常类似,不过最大的区别在于,Map 结构可以用其他类型作为 key,例如数组、对象等。
Map 可以参照这篇博客Map 和 WeakMap
示例代码:
10、Promise
Promise 是 es6 的精华之一,他非常适用于异步处理。
Promise 对象在使用的时候,分为两部分,第一部分是
new Promise
这一步,第二部分是对返回的 Promise 实例进行处理的内容。因为是通过执行
resolve
或reject
来改变 Promise 的状态,从而决定执行 then 的时机的(类似回调函数),以及执行的哪一个。因此写起来和回调函数相近,但是可以连写,避免回调地狱的情况。关于 Promise 的详细介绍请阅读Promise(1) 基础知识及之后三篇博客
如示例代码(对比普通 ajax 和 promise)(另注:为了方便理解,仿 jQuery 的写法,并且没有用 jQuery 的
$.ajax().then()
这种写法)显然,then 连写比回调函数的写法要方便一些。
如果面对的是特殊需求,比如是多个 ajax 请求全部完成后,再执行执行函数,那么 Promise 的优势会更大一些,而非 Promise 写法要麻烦很多。
甚至如果要对错误进行处理,那么 Promise 写法会更方便。
不过这里只是小结,就不细说了。
11、class
class 是好东西。
有了 class 后,写构造函数、写类的继承的难度,下降了很多很多。
先附我的博文class(1) 基本概念,以及之后 5 篇博文。
由于很简单,给一个示例大约就能理解这个是怎么用的:
12、es6 模块
es6 的模块不同于以往的 CommonJS(node 用,服务器环境),AMD(RequireJS 的规范,浏览器环境,依赖前置)、CMD(SeaJS 定义的规范,浏览器环境,依赖就近)。
他的特点有两个:
缺点是:
详细说明阅读这篇博客:es6 的 import 和 export,另外三个规范阅读这篇博客AMD、CMD、CommonJS
基本使用方式如示例代码:
13、async 函数
这个并不是 es6 的,而是 es2017(又称 es8)的内容。
可以认为 async 函数是 Generator 函数的语法糖,详细说明参照这篇博客:async 函数。
他的前置知识比较多,包括 Iterator 遍历器、Generator 状态机、Thunk 函数(自动执行 Generator 函数)。
简单的说,假如有多个异步请求,你需要让这些起步请求依次执行,例如在执行完前一个之后,再执行后一个。那么你就需要 async 函数了。
async 函数可以让你写这种请求如同写同步函数一样简单(对比【10】中的 Promise 更简单)。
以下示例是基于【10】中的代码,在最后一步执行的时候,改用 async 函数来完成
可以发现,async 让连续异步调用像写同步函数一样简单。
14、ESLint
规范化开发,建议还是用 ESLint 来帮忙检查吧。不会这个怎么行?
这里直接给一个阮一峰写的文章,等以后我再单独补一篇详细用法的博客。
ESLint 的使用
15、小结
es6 常用内容基本就以上 13 点。
虽然 es6 实际包括了很多知识,例如:
但实际常用的就以上这些,如果只是日常使用的话,熟悉以上内容足够了。
但若要做的更好,那么应该深入学习,es6 新增的很多内容,是将传统后端语言的一些很好的思想,搬到 JavaScript 来,让 js 规范化。
对于专精于前端的同学,学习 es6 的过程中,可以学习到这些来自于其他语言的精华,因此建议至少完整的看一遍,勿要只满足于常用的这些 API。
我的技术交流 QQ 群:387017550,感兴趣的欢迎加入和我进行讨论,群里有很多 BAT 的同学,也会解答常见问题。
https://juejin.im/post/5ee9a1556fb9a0586320a395?utm_source=gold_browser_extension
The text was updated successfully, but these errors were encountered: