写点什么

读深入 ES6 记 [一]

用户头像
Daniel
关注
发布于: 2021 年 06 月 08 日
读深入ES6记[一]

划重点了,有没像期末考时老师给题目范围的感觉,呵呵。


该笔记系列主要是在阅读深入ES6系列文章时,自己印象较为深刻的部分的记录,也是自己对学习内容的一些总结,目的在于当自己有点忘却的时候,可以快速看看自己这里所写内容就可以记起大概。当然,如果正在阅读本篇文章的你们,可以通过该文章对 ES6 有个快速简单的了解,那就太太好了。闲话不多说,开始写写写。。。


第一章:ES6 介绍


1.ECMAScript 是一个程序语言标准,它描述了这门语言的语法,类型,标准库等。


2.Javascript 是它的实现和扩展(微软的 Jscript 也是其实现和扩展)。


3.ES6 就是指 ECMAScript 这个标准的第 6 版


4.文中提到 ES5 中引入了一些新特性,其中Object.create()让我较感兴趣,跟对象的继承实现有关系,我们看下 MDN 对该方法的描述:


The Object.create() method creates a new object with the specified prototype object and properties.


即通过指定原型 object 和属性来创建新的 object,怎么用在继承实现上,代码伺候:


function Super() {  this.name = 'super';}Super.prototype.sayName = function () {  console.log(this.name);}
function Sub() { Super.call(this);}// Sub.prototype = new Super(); // 用new的方式继承原型Sub.prototype = Object.create(Super.prototype); // 用Object.create的方式继承原型Sub.prototype.constructor = Sub;
复制代码


Object.create()更优,因为这样的写法来继承 prototype 更直观易懂,而且子类的 prototype 不会包含多余的父类属性(如例子中的 name)


有没同学会问用new的方式,子类的 prototype 会包含父类的属性,那这个属性会不会造成影响?答案是不会滴,因为我们在子类的构造函数中调用了Super.call(this)来达到每个子类的实例都拥有自己的一份属性(name),而作用域是先从实例来查看该属性是否存在,不存在才去 prototype 查找。很明显实例中存在,所以子类中的 prototype 的属性其实没什么用


第二章:迭代器(Iterator)与 for-of 循环


1.避免for-in来遍历数组,因为它是一个坑,为啥?


坑 1


var arr = ['foo', 'bar'];for (var idx in arr) {  console.log(arr[idx]);}
复制代码


idx是字符串,如果你把它当数字,进行了类似这样的计算idx + 1就悲剧了,因为它的值会像这样"01","11"。为啥它是字符串而不是数字呢?因为人家本来就设计来遍历对象的嘛,对象的 key 一般都是字符串嘛


坑 2


var arr= ['a', 'b'];arr.key = 'value';for (var idx in arr) {  console.log(idx); // 输出"0" "1" "key"}
复制代码


for-in 会遍历对象的所有可枚举的属性,包括自定义和原型中的属性,所以有些行为可能不如你所愿


2.for-of遍历数组数据的理想作法


为啥理想呢?因为它没有for-in的坑,把上面for-in的代码用for-of试一下就清楚了还有循环中我们总是希望在某些条件下跳过或者打断循环,在for-of里面是可以通过breakcontinuereturn控制循环


3.哪些数据类型可以使用for-of


实现了迭代器接口方法([Symbol.iterator]()和 next())的对象都可以使用。内建的 Array,Map,Set 等自实现了迭代器接口,所以可以使用for-of。普通对象 Object 是不能使用for-of的,因为,来,你说一下,哈。试下这里的代码,看会报什么错:for (var val of {a: 1}) {}


4.让普通对象 Object 也能for-of


上面提到需要实现迭代器接口才能使用for-of来遍历数据,那我们来看看怎么让普通对象 Object 也能拥有此特性注意:以下仅用于举例说明,如想用于生产环境,风险自负哈


Object.prototype[Symbol.iterator] = function() {  return this; // 返回迭代器对象。一个迭代器必须实现了next接口,返回值格式为{done: [bool], value: }};Object.prototype.next = function () {  this.currentIdx = (this.currentIdx === undefined ? -1 : this.currentIdx) + 1;  let keys = Object.keys(this);  let keyTotal = keys.length - 1; // 排除掉currentIdx这个属性  let done = keyTotal < this.currentIdx + 1;  let key = done ? null : keys[this.currentIdx];  let value = key ? this[key] : undefined;  return {done: done, value: value};};
obj = {a: 1};for (let val of obj) { console.log(val);}
复制代码


5.Why [Symbol.iterator]?代码不好看有木有


有没人有疑问,为啥要用[Symbol.iterator],这看上去不太优雅呀,改成 iterator 多好,比如Object.prototype.iterator = function() {}。制定标准的人还是考虑得很周到的,万一别人的对象已经有 iterator 方法呢?所以为了不造成冲突,用 Symbol 是个好做法(Symbol 是什么东东,后面会讲到,不懂的先带着疑问看下去吧)


6.为啥用迭代器设计模式?不就遍历数据而已吗?


有思考过这个问题的人举个手呗(好吧,反正我看不到)。有没人说数组用自己的遍历方式,Map 用自己的遍历方式等就行拉。当然,可以,但只能说思想境界不同而已。迭代器设计模式的引入是为了让调用者可以不关心数据的存储细节(Array?Map?Set?or other...),用统一的接口(比如 Javascript 这里用 for-of)来遍历数据,而要实现遍历的对象也只需实现迭代器规定的接口即可。常见的迭代器的接口设计有:以 Java 为代表:hasNext 和 next 方法以 Python 为代表:只有 next 方法,无值时抛异常以 Javascript 为代表:只有 next 方法,返回对象中用 done 属性来表明是否遍历完成


7.用简单等价代码理解for-of


我们以上面实现了迭代器的普通对象来继续这个话题


var obj = {a: 1};
for (let val of obj) { console.log(val);}
复制代码


从以下简单等价的代码可看出for-of的基本逻辑,当然,实际的for-of实现会更复杂些


var obj = {a: 1};
var iterator = obj[Symbol.iterator]();var result = iterator.next();while(!result.done) { var value = result.value;
// 一些语句 console.log(value);
result = iterator.next();}
复制代码




这就是第一,二章的学习情况,接下来可继续看《读深入ES6记[二]》


--EOF--

发布于: 2021 年 06 月 08 日阅读数: 19
用户头像

Daniel

关注

一源一世界 2019.03.03 加入

ncform / ncgen / nice-hooks 开源项目作者

评论

发布
暂无评论
读深入ES6记[一]