前端 es6特性 es6文档_第1页
前端 es6特性 es6文档_第2页
前端 es6特性 es6文档_第3页
前端 es6特性 es6文档_第4页
前端 es6特性 es6文档_第5页
已阅读5页,还剩19页未读 继续免费阅读

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Es6文档简介ES6, 全称 ECMAScript 6.0 ,是 JavaScript 的下一个版本标准,2015.06 发版。ES6 主要是为了解决 ES5 的先天不足,比如 JavaScript 里并没有类的概念,但是目前浏览器的 JavaScript 是 ES5 版本,大多数高版本的浏览器也支持 ES6,不过只实现了 ES6 的部分特性和功能。特性Table of Contents var 与 let / const 声明 代码执行块替换立即执行函数 箭头函数 字符串 解构 模块 参数 类 Symbols Maps WeakMaps Promises Generators Async Awaitvar versus let / const除了var以外,我们现在多了两个新的标识符来声明变量的存储,它们就是let和const。不同于var,let和const语句不会造成声明提升。一个var的例子:var snack = Meow Mix;function getFood(food) if (food) var snack = Friskies; return snack; return snack;getFood(false); / undefined让我们再观察下面语句中,使用let替换了var后的表现:let snack = Meow Mix;function getFood(food) if (food) let snack = Friskies; return snack; return snack;getFood(false); / Meow Mix当我们重构使用var的老代码时,一定要注意这种变化。盲目使用let替换var后可能会导致预期意外的结果。注意:let和const是块级作用域语句。所以在语句块以外引用这些变量时,会造成引用错误ReferenceError。console.log(x);let x = hi; / ReferenceError: x is not defined最佳实践: 在重构老代码时,var声明需要格外的注意。在创建一个新项目时,使用let声明一个变量,使用const来声明一个不可改变的常量。Replacing IIFEs with Blocks我们以往创建一个立即执行函数时,一般是在函数最外层包裹一层括号。ES6支持块级作用域(更贴近其他语言),我们现在可以通过创建一个代码块(Block)来实现,不必通过创建一个函数来实现,(function () var food = Meow Mix;();console.log(food); / Reference Error使用支持块级作用域的ES6的版本: let food = Meow Mix;console.log(food); / Reference ErrorArrow Functions一些时候,我们在函数嵌套中需要访问上下文中的this。比如下面的例子:function Person(name) = name;Ptotype.prefixName = function (arr) return arr.map(function (character) return + character; / Cannot read property name of undefined );一种通用的方式是把上下文中的this保存在一个变量里:function Person(name) = name;Ptotype.prefixName = function (arr) var that = this; / Store the context of this return arr.map(function (character) return + character; );我们也可以把this通过属性传进去:function Person(name) = name;Ptotype.prefixName = function (arr) return arr.map(function (character) return + character; , this);还可以直接使用bind:function Person(name) = name;Ptotype.prefixName = function (arr) return arr.map(function (character) return + character; .bind(this);使用箭头函数,this的值不用我们再做如上几段代码的特殊处理,直接使用即可。上面的代码可以重写为下面这样:function Person(name) = name;Ptotype.prefixName = function (arr) return arr.map(character = + character);最佳实践:使用箭头函数,再也不用考虑this的问题了。当我们编写只返回一个表达式值的简单函数时,也可以使用箭头函数,如下:varsquares = arr.map(function(x)returnx * x );/ Function Expressionconst arr = 1, 2, 3, 4, 5;const squares = arr.map(x = x * x); / Arrow Function for terser implementation最佳实践:尽可能地多使用箭头函数。Strings在ES6中,标准库也被同样增强了,像字符串对象就新增了.includes()和.repeat()方法。.includes( )var string = food;var substring = foo;console.log(string.indexOf(substring) -1);现在,我们可以使用.inclues()方法,替代以往判断内容 -1的方式。.includes()方法会极简地返回一个布尔值结果。const string = food;const substring = foo;console.log(string.includes(substring); / true.repeat( )function repeat(string, count) var strings = ; while(strings.length count) strings.push(string); return strings.join();在ES6中,我们可以使用一个极简的方法来实现重复字符:/ String.repeat(numberOfRepetitions)meow.repeat(3); / meowmeowmeowTemplate Literals使用字符串模板字面量,我可以在字符串中直接使用特殊字符,而不用转义。vartext =This string contains double quotes which are escaped.;lettext =This string contains double quotes which dont need to be escaped anymore.;字符串模板字面量还支持直接插入变量,可以实现字符串与变量的直接连接输出。var name = Tiger;var age = 13;console.log(My cat is named + name + and is + age + years old.);更简单的版本:const name = Tiger;const age = 13;console.log(My cat is named $name and is $age years old.);ES5中,我们要这样生成多行文本:var text = ( catn + dogn + nickelodeon);或者:var text = cat, dog, nickelodeon.join(n);字符串模板字面量让我们不必特别关注多行字符串中的换行转义符号,直接换行即可:let text = ( catdognickelodeon);字符串模板字面量内部可以使用表达式,像这样:let today = new Date();let text = The time and date is $today.toLocaleString();Destructuring解构让我们可以使用非常便捷的语法,直接将数组或者对象中的值直接分别导出到多个变量中,Destructuring Arrays解构数组var arr = 1, 2, 3, 4;var a = arr0;var b = arr1;var c = arr2;var d = arr3;let a, b, c, d = 1, 2, 3, 4;console.log(a); / 1console.log(b); / 2Destructuring Objects解构对象var luke = occupation: jedi, father: anakin ;var occupation = luke.occupation; / jedivar father = luke.father; / anakinlet luke = occupation: jedi, father: anakin ;let occupation, father = luke;console.log(occupation); / jediconsole.log(father); / anakinModulesES6之前,浏览器端的模块化代码,我们使用像Browserify这样的库,在Node.js中,我们则使用require。在ES6中,我们现在可以直接使用AMD 和 CommonJS这些模块了。Exporting in CommonJSmodule.exports = 1;module.exports = foo: bar ;module.exports = foo, bar;module.exports = function bar () ;Exporting in ES6在ES6中,提供了多种设置模块出口的方式,比如我们要导出一个变量,那么使用变量名:export let name = David;export let age = 25;还可以为对象导出一个列表:function sumTwo(a, b) return a + b;function sumThree(a, b, c) return a + b + c;export sumTwo, sumThree ;我们也可以使用简单的一个export关键字来导出一个结果值:export function sumTwo(a, b) return a + b;export function sumThree(a, b, c) return a + b + c;最后,我们可以导出一个默认出口:function sumTwo(a, b) return a + b;function sumThree(a, b, c) return a + b + c;let api = sumTwo, sumThree;export default api;最佳实践:总是在模块的最后使用export default方法。它让模块的出口更清晰明了,节省了阅读整个模块来寻找出口的时间。更多的是,在大量CommonJS模块中,通用的习惯是设置一个出口值或者出口对象。最受这个规则,可以让我们的代码更易读,且更方便的联合使用CommonJS和ES6模块。Importing in ES6ES6提供了好几种模块的导入方式。我们可以单独引入一个文件:importunderscore;这里需要注意的是,整个文件的引入方式会执行该文件内的最上层代码。就像Python一样,我们还可以命名引用:import sumTwo, sumThree frommath/addition;我们甚至可以使用as给这些模块重命名:import sumTwo as addTwoNumbers, sumThree as sumThreeNumbers from math/addition;另外,我们能引入所有的东西(原文:import all the things)(也称为命名空间引入)import*asutilfrommath/addition;最后,我们能可以从一个模块的众多值中引入一个列表:import * as additionUtil from math/addtion;const sumTwo, sumThree = additionUtil;像这样引用默认对象:import api from math/addition;/ Same as: import default as api from math/addition;我们建议一个模块导出的值应该越简洁越好,不过有时候有必要的话命名引用和默认引用可以混着用。如果一个模块是这样导出的:/ foos.jsexport foo as default, foo1, foo2 ;那我们可以如此导入这个模块的值:importfoo, foo1, foo2 fromfoos;我们还可以导入commonjs模块,例如React:import React from react;const Component, PropTypes = React;更简化版本:importReact, Component, PropTypes fromreact;注意:被导出的值是被绑定的(原文:bingdings),而不是引用。所以,改变一个模块中的值的话,会影响其他引用本模块的代码,一定要避免此种改动发生。Parameters在ES5中,许多种方法来处理函数的参数默认值(default values),参数数量(indefinite arguments),参数命名(named parameters)。ES6中,我们可以使用非常简洁的语法来处理上面提到的集中情况。Default Parametersfunction addTwoNumbers(x, y) x = x | 0; y = y | 0; return x + y;ES6中,我们可以简单为函数参数启用默认值:function addTwoNumbers(x=0, y=0) return x + y;addTwoNumbers(2, 4); / 6addTwoNumbers(2); / 2addTwoNumbers(); / 0Rest ParametersES5中,遇到参数数量不确定时,我们只能如此处理:function logArguments() for (var i=0; i / do somethingSymbol.for(key)使用Symbol.for(key)也是会创建一个不可改变的Symbol对象,但区别于上面的创建方法,这个对象是在全局中可以被访问到的。调用两次Symbol.for(key)会返回相同的Symbol实例。提示:这并不同于Symbol(description)。Symbol(foo) = Symbol(foo) / falseSymbol.for(foo) = Symbol(foo) / falseSymbol.for(foo) = Symbol.for(foo) / true一个Symbols常用的使用场景,是需要使用特别Symbol.for(key)方法来实现代码间的协作。这能让你在你的代码中,查找包含已知的接口的第三方代码中Symbol成员。(译者:这句话好难翻。原文:This can beachieved by having your code look for a Symbol member on object arguments from third parties that contain some known interface. )举个例子:function reader(obj) const specialRead = Symbol.for(specialRead); if (objspecialRead) const reader = objspecialRead(); / do something with reader else throw new TypeError(object cannot be read); 之后在另一个库中:const specialRead = Symbol.for(specialRead);class SomeReadableType specialRead() const reader = createSomeReaderFrom(this); return reader; 注意:Symbol.iterable在ES6中像其他可枚举的对象,如数组,字符串,generators一样,当这个方法被调用时会激活一个枚举器并返回一个对象。MapsMaps是一个Javascript中很重要(迫切需要)的数据结构。在ES6之前,我们创建一个hash通常是使用一个对象:var map = new Object();mapkey1 = value1;mapkey2 = value2;但是,这样的代码无法避免函数被特别的属性名覆盖的意外情况: getOwnProperty( hasOwnProperty: Hah, overwritten, Pwned); TypeError: Property hasOwnProperty is not a functionMaps让我们使用set,get和search操作数据。let map = new Map(); map.set(name, david); map.get(name); / david map.has(name); / trueMaps最强大的地方在于我们不必只能使用字符串来做key了,现在可以使用任何类型来当作key,而且key不会被强制类型转换为字符串。let map = new Map( name, david, true, false, 1, one, , object, function () , function);for (let key of map.keys() console.log(typeof key); / string, boolean, number, object, function提示:当使用map.get()判断值是否相等时,非基础类型比如一个函数或者对象,将不会正常工作。有鉴于此,还是建议使用字符串,布尔和数字类型的数据类型。我们还可以使用.entries()方法来遍历整个map对象:for (let key, value of map.entries() console.log(key, value);WeakMaps在ES5之前的版本,我们为了存储私有数据,有好几种方法。像使用这种下划线命名约定:class Person constructor(age) this._age = age; _incrementAge() this._age += 1; 在一个开源项目中,命名规则很难维持得一直很好,这样经常会造成一些困扰。此时,我们可以选择使用WeakMaps来替代Maps来存储我们的数据:let _age = new WeakMap();class Person constructor(age) _age.set(this, age); incrementAge() let age = _age.get(this) + 1; _age.set(this, age); if (age 50) console.log(Midlife crisis); 使用WeakMaps来保存我们私有数据的理由之一是不会暴露出属性名,就像下面的例子中的Reflect.ownKeys(): const person = new Person(50); person.incrementAge(); / Midlife crisis Reflect.ownKeys(person); / 一个使用WeakMaps存储数据更实际的例子,就是有关于一个DOM元素和对该DOM元素(有污染)地操作:let map = new WeakMap();let el = document.getElementById(someElement);/ Store a weak reference to the element with a keymap.set(el, reference);/ Access the value of the elementlet value = map.get(el); / reference/ Remove the referenceel.parentNode.removeChild(el);el = null;value = map.get(el); / undefined上面的例子中,一个对象被垃圾回收期给销毁了,WeakMaps会自动的把自己内部所对应的键值对数据同时销毁。提示:结合这个例子,再考虑下jQuery是如何实现缓存带有引用的DOM元素这个功能的,使用了WeakMaps的话,当被缓存的DOM元素被移除的时,jQuery可以自动释放相应元素的内存。通常情况下,在涉及DOM元素存储和缓存的情况下,使用WeakMaps是非常适合的。PromisesPromises让我们让我们多缩进难看的代码(回调地狱):func1(function (value1) func2(value1, function (value2) func3(value2, function (value3) func4(value3, function (value4) func5(value4, function (value5) / Do something with value 5 ); ); ); ););写成这样:func1(value1) .then(func2) .then(func3) .then(func4) .then(func5, value5 = / Do something with value 5 );在ES6之前,我们使用bluebird或者Q。现在我们有了原生版本的 Promises:new Promise(resolve, reject) = reject(new Error(Failed to fulfill Promise) .catch(reason = console.log(reason);这里有两个处理函数,resolve(当Promise执行成功完毕时调用的回调函数) 和reject(当Promise执行不接受时调用的回调函数)Promises的好处:大量嵌套错误回调函数会使代码变得难以阅读理解。使用了Promises,我们可以让我们代码变得更易读,组织起来更合理。此外,Promise处理后的值,无论是解决还是拒绝的结果值,都是不可改变的。下面是一些使用Promises的实际例子:var fetchJSON = function(url) return new Promise(resolve, reject) = $.getJSON(url) .done(json) = resolve(json) .fail(xhr, status, err) = reject(status + err.message); );我们还可以使用Promise.all()来异步的并行处理一个数组的数据。var urls = /items/1234, /items/4567;var urlPromises = urls.map(fetchJSON);Promise.all(urlPromises) .then(function (results) results.forEach(function (data) ); ) .catch(function (err) console.log(Failed: , err); );Generators就像Promises如何让我们避免回调地狱一样,Generators也可以使我们的代码扁平化,同时给予我们开发者像开发同步代码一样的感觉来写异步代码。Generators本质上是一种支持的函数,随后返回表达式的值。Generators实际上是支持暂停运行,随后根据上一步的返回值再继续运行的一种函数。下面代码是一个使用generators函数的简单例子:function* sillyGenerator() yield 1; yield 2; yield 3; yield 4;var generator = sillyGenerator(); console.log(generator.next(); / value: 1, done: false console.log(generator.next(); / value: 2, done: false console.log(generator.next(); / value: 3, done: false console.log(generator.next(); / value: 4, done: false 就像上面的例子,当next运行时,它会把我们的generator向前“推动”,同时执行新的表达式。我们能利用Generators来像书写同步代码一样书写异步代码。/ Hiding asynchronousity with Generatorsfunction request(url) getJSON(url, function(response) generator.next(response); );这里我们写个generator函数将要返回我们的数据:function* getData() var entry1 = yield request(http:/some_api/item1); var data1 = JSON.parse(entry1); var entry2 = yield request(http:/some_api/item2); var data2 = JSON.parse(entry2);借助于yield,我们可以保证entry1确实拿到数据并转换后再赋值给d

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论