背景介绍
在之前的高级篇已经给出了ES6在函数方法和循环上做的的优化和改变,那最后这一篇就来给ES6的新特性画上一个圆满的句号吧:),基础篇,进阶篇,高级篇的传送门:
特性重点
一、【重点】Set和Map数据结构
ES6终于有了Set和Map,当年苦苦在搜索引擎查如何用JS实现Map的初学开发者们应该要眼眶湿润了:
// set
let set =new Set( ['red','green','blue'] );
for(let x of set) { console.log(x); }
// map
let map =new Map( [ ['F','no'], ['T','yes'] ] );
for( let [key, value] of map) { console.log(key, value); }
二、【重点】Generator 函数
说实话,Generator函数应该整个ES6中最难理解,最抽象的一部分了。很多搜索出来的定义和解释都相当不接地气,相信初学的人搜索后都会一脸懵逼。其实,如果从ES6的大方向和设计目标上分析,就好理解的多。
首先ES6除了更方便的语法和更多的实用功能,也是在为JS工程化,模块化,甚至更直接点说就是为了构建大型系统架构做努力。受限制于脚本,而且初期设计不佳,一直以来这样的目标都难以实现。而且JS单线程的特性,使得高并发的处理需求,不得不通过大量的回调机制来“曲线救国”,对,我这里要用的就是这个词。
虽然Node以异步回调高性能著称,但是这背后却是一种无可奈何,更多的还是一种宣传上的妥协,如果Node能完美用多线程,今天的发展一定更猛,完全超越Java也不是梦!!!
先说说为什么回调机制成为了限制JS发展的一大因素。其实异步回调机制不是什么新鲜的产物,更不是什么划时代的新技术,早在C语言的时代,就已经有了——函数指针。将函数指针作为参数传递,就是异步回调。回调的确是不阻塞,而且性能更好。
但是回调也有巨大的缺陷——就是写法上复杂,并且不符合人类的逻辑思维!是的,回调并不符合人类的逻辑思维,这也是为什么回调学习曲线特别陡峭的原因。这个世界是异步的,但人的思想是同步的。人希望异步地处理事情,例如开一家公司,有大大小小许多的事情去做,BOSS希望的是雇一群员工去做,而不是雇一群助理来通知自己什么时候该做什么事情。
Node的回调机制本质上是一种事件消息模型的设计模式的应用,通知你去做一件事情,但是我不必等你做完,而是等你完成了再来告诉我。Node非常极端,几乎全是异步回调。这样带来的问题就是当有同步需求的时候,很难满足。从而github上就产生了许许多多的流程控制框架,各种号称能完美解决异步流程的东西产生。
从来没有一门编程语言是需要专门的流程控制框架,流程管理工具等去协助处理“流程”的,因为这是一种讽刺不是么。。。所谓“编程”本质就是在表达人类的思维。如果这一门语言不能很好地表达人类思维,而是需要带上一个助听器,扩音器才行,那这又有什么意义?
虽然看到可能很多的人会反驳我,说多线程Out了,异步回调一点不比多线程差等等。当然,一千个读者心中就由一千个哈姆雷特,在此我不做过多辩解。但是我的观点还是多线程才是处理高并发,高性能更好的解决方案,异步回调可以作为补充,但绝对不是到影响了同步思维,同步流程的地步。现实中同步需求一点不比异步需求少,相反可能更多。我坚信Node未来一定会完美实现多线程。
好的,跑偏了,继续说回Generator 函数,它的推出,是ES6为解决异步回调带来的嵌套式写法噩梦。这里用大白话解释,不说玄乎的话语——Generator 函数就是一个能控制自己运行流程的机制。后端的开发者们应该会有了解,这不就是——状态机吗?
是的,这又是一种设计模式了。没错,因为异步回调实在太难搞了,如果不再语言层面提供解决方案,恐怕以后JS的代码就越来越难维护。所以ES6推出了Generator 函数,下面来看看它的真面目:
function* helloWorldGenerator(){ yield 'hello'; yield 'world';}
var hw= helloWorldGenerator();
hw.next() // { value: 'hello', done: false }
hw.next() // { value: 'world', done: false }
通过星号*定义,使用yield来控制流程,每执行一次next前进一步,非常典型的流程状态控制。
三、【重点】Promise对象
ES6原生提供了Promise对象。“所谓Promise对象,就是代表了未来某个将要发生的事件”。这里我翻译一下,其实Promise也是因为异步回调嵌套太多,导致逻辑深入不可自拔引发JS发展瓶颈,从而产生的解决方案。本质就是同步流程语言的返回值。上一步结果出参作为下一步入参,可以写出链式风格的代码来代表同步逻辑。
getJSON("/post/1.json").then( function(post) {
return getJSON(post.commentURL);
})
.then( function(comments){
// 对comments进行处理
});
四、【重点】Class和Module
class Point{
constructor(x, y) { this.x = x; this.y = y; }
toString() { return'('+this.x+', '+this.y+')'; }
}
面向对象语法糖,有了它,定义类,写对象就更简单了。
最后就是模块构建了,这么多年了JS竟然都没有模块构建,也是逼得社区诞生了CommonJS和AMD。ES6的模块构建包含两个命令,import和export(有导出才有导入)。
export {firstName, lastName, year}; // profile
import {firstName, lastName, year} from'./profile';
如果想要输出匿名函数,可以使用export default命令
export default function(){ console.log('foo'); }// export-default
import customName from'./export-default';
customName();// 'foo'
总结
这最后的一章基本上都是ES6对异步流程控制,优化代码逻辑做出的努力,这些努力很多也将会成为ES7的基础,例如生成器函数之后的async...await...。不过不管怎么样,还是非常期待未来JavaScript对多线程的支持,能够在同步和异步的取舍上达到一个平衡,任何事情,走极端了总是不好。ES6重点系列的文章在这就告一段落,后续我个人还会持续在简书上写各类的技术文章,也算是作为我个人点滴的积累吧。
本文基于阮一峰的ECMAScript 6 系列文章和众多网络散文资料汇聚。在此给出原文链接,上面给出的重点一览,都可以在下面链接找到更为详尽的讲解:
如果有任何的批评建议,BUG反馈,问题反馈,或是想法建议,帮助支持,个人都十分欢迎,我个人的联系方式如下:)
作者:cheneyxu
邮箱:457299596@qq.com
QQ:457299596
关于:XServer官网