Es6笔记

前言

笔记仅记录了相比于第一次学习,重新理解的知识点
完整内容详见:《ECMAScript 6 入门》 阮一峰

总结

经历两个星期结合ES6的React实践,决定再回头看一遍阮一峰的ES6教程,发现收获多多,常看常新。
第一遍看时,比较敷衍,没有实践自然也理解不深,综合来说,阮一峰的教程更适合查漏补缺,而不是作为入门教材。

索引

  1. 解构赋值的用途
  2. 尾调用优化
  3. 扩展运算符的用途
  4. 数组的方法扩展
  5. 对象
  6. Set类型 : distinct Array
  7. Map类型:可扩展键名,值—值对
  8. Proxy对象
  9. Promise对象
  10. Iterator 迭代器
  11. Generator生成器
  12. async函数
  13. Class 类

1. 解构赋值的用途

① 交换变量值: [x, y] = [y, x]
② 函数返回值的获取更便利: let [a, b, c ] = func()
③ 函数无序传参
有序传参:function func([x,y,z]) { } func([1,2,3])
无序传参:function func({x, y, z}) { } func({z: 3, y: 2 , x: 1})
④ 提取JSON数据更方便
⑤ 函数传参可设置默认值,如预设Ajax请求的参数
当传入Ajax请求的参数不声明async与cache值,默认都为true
jQuery.ajax = function (url, { async = true, cache = true}) {};
⑥ Map类型取键名/值 : for ( let [key, value] of map) { }
⑦ 加载CommonJS模块中的指定方法: import { func1 , func2 } from '../common.js'

2. 尾调用优化

在函数的最后一步(即return)中调用另一个函数,形如return g(a,b);,叫做尾调用。
存储于内存中的函数调用记录(包含了调用内存位置、变量等信息),叫做调用帧,嵌套函数的调用帧形成了调用栈;这很浪费内存。
因此在return句中采用尾调用,当内层函数的调用不再用到外层函数中的信息,就可用最新内层函数的调用帧取代外层函数的调用帧,节省内存。

3. 扩展运算符的用途

① 取代concat()合并数组: let arr = [...arr1, ...arr2];
② 与解构赋值并用,截取部分数组: let [item, ...rest] = array;
③ 分解对象类型的函数返回值: var { data, code, msg } = getData();
④ 字符串转数组: [...'hello] 等同于 'hello'.split('');
⑤ 正确识别32位的Unicode字符串: [ ...str ].length 获取unicode字符串正确长度

4. 数组的方法扩展

① array.find(function) :查找第一个符合条件的数组元素
② array.findIndex() :与indexOf功能相同,但findIndex优于可查找NaN元素
③ new Array(5).fill(0) :创建数组并且初始化为全0
④ 数组元素遍历
array.keys() :遍历键名
array.values() :遍历键值
array.entries() :遍历键值对
⑤ array.includes(value): 数组查找,可查找NaN

5. 对象

① let a = { [key]: value} :用表达式作键名
② Object.is(value1, value2 ): 严格一致,不会自动转换类型,准确性高于“===”
③ Object.assign(target, obj1, obj2 ): 合并对象属性到第一个参数中;是浅拷贝(符合类型为引用)
④ object.__proto__属性指向Object.prototype属性
object.__proto__属性推荐使用的三个操作方法:
Object.setPrototypeOf(object, prototype)
Object.getPrototypeOf(obj);
Object.create()
⑤ prototype__proto__属性
Array.prototype:Array原型的所有方法
new Array(3).__proto__ : 原型实例的自有属性方法,内包含了Array.prototype中的所有方法
⑥ 对象的扩展:let { x, y, ...z } = { x: 1, y: 2, a: 3 , b: 4} ; 则 z = { a: 3 , b: 4 }

6. Set类型 : distinct Array

① .add() 
② .size
③ .delete()
④ .has(value)
⑤ .clear()
⑥ Set转数组: Array.from(set)
数组去重: Array.from (new Set(array))

7. Map类型:可扩展键名,值—值对

① .size
② .set(key, value)
③ .get(key)
④ .has(key)
⑤ .delete(key)
⑥ .clear()
⑦ 遍历的顺序即插入的顺序
⑧ Map转数组: ...map

8. Proxy对象

进程与对象实体之间的拦截层

9. Reflect对象

用于部署对象的新方法;可以通过Reflect对象拿到语言内部的方法,如Object.defineProperty

10. Promise对象

① 封装了一个函数
② 对内部函数返回的resolvereject进行分发处理(.then.catch
③ Promise新建后,立即执行

11. Iterator 迭代器

① Iterator.next()的返回值: {value: 'value', done: false} 或 { value: undefined, done: true}
② 悄悄调用了可遍历数据的Iterator的情况:
解构赋值有序对象(数组、set)、
扩展运算符...
yield* 表达式: yield* [2,3,4] 等同于 yield 2; yield 3; yield 4;
③ let ... in :遍历键名
④ let ... of:遍历键值(适用于有Iterator接口的数据)

12. Generator生成器

① 相当于一个封装了多个状态的状态机
② 作用:生成并且返回一个遍历器对象
③ 调用后并不立即执行,而是返回一个指向内部状态的指针对象(遍历器对象)
④ 调用iterator.next(),才是真正执行内部函数的时机
⑤ yield可以嵌入普通语句中,但要放在圆括号中: console.log( 'hello' + (yield 123) );
⑥ yield表达式本身的返回值是undefined,但可以用next(value)对上一个yield表达式赋值
⑦ yield * generator():在一个生成器函数中调用另一个生成器函数
⑧ 封装异步函数,实现回调

function* demo () {
    // do something  Part1 
    yield go();           // 相当于分离了异步的两个阶段,part1与part2
    // do something  Part2
}

let g = demo();
g.next();      // 执行part1
g.next();      // part1执行完之后,再执行part2

⑨ 重点理解:
Generator 函数是分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行。
在第一次调用.next()时,执行到yield语句(yield语句本身也被执行)。等下一次next调用,执行下一段包含yield语句的代码段。

function* demo () {
    do thing 1     
    yield y1;
<---第一次执行next,执行到此处---->
    do thing 2
    yield y2;
<---第二次执行next,执行到此处---->
    do thing 3 
    yield y3;
<---第三次执行next,执行到此处---->
    do thing 4 
    yield y4;
<---第四次执行next,执行到此处---->
}
// 代码实例
  var a = 0;

  function* demo() {
    console.log('in demo  a = 3')
    console.log(yield a=3);
    console.log('in demo  a = 4')
    console.log(yield a=4);
    console.log('in demo  a = 5')
    console.log(yield a=5);
  }

  let g = demo();
  console.log('首次next');
  console.log(a);
  console.log( g.next());
  console.log(a);
  console.log('二次next')
  console.log(a);
  console.log( g.next())
  console.log(a);
  console.log('三次next')
  console.log(a);
  console.log( g.next())
  console.log(a);
yield实例运行的console结果
yield实例运行的console结果

13. async函数

是generator的语法糖,简化了异步操作。相比generator,async具有以下优点:
① 内置执行器,单行调用即可完成generator函数的所有.next()
② 更具有语义性
③ 适用性更广
yield命令:只能后跟 Thunk 或Promise
await命令:可后跟Promise对象与原始值
④ async函数的返回值是Promise对象
async将generator返回的Iterator对象自动执行后,并将结果封装为一个Promise对象,便于后期处理。
return await 123; ==> 转为resolve状态的Promise对象
async中return语句返回值,传入.then()作回调参数。
return Promise.reject('出错了'); ==> 转为reject状态的Promise对象
async中抛出错误,返回reject状态的Promise对象,传入.catch()方法
⑤ forEach中的async是并发操作的,应该改用for循环

// 不推荐用forEach写法
function dbFuc(db) { //这里不需要 async
  let docs = [{}, {}, {}];

  // 可能得到错误结果
  docs.forEach(async function (doc) {
    await db.post(doc);
  });
}

// 推荐用for循环
async function dbFuc(db) {
  let docs = [{}, {}, {}];

  for (let doc of docs) {
    await db.post(doc);
  }
}

14. Class 类

① super
super(): 代表父类的构造函数传入父类的this,等同于Class.prototype.constructor.call(this)
super:指向父类的原型对象,等同于Class.prototype,可用于调用父类的静态方法
② prototype 与__proto__
子类的__proto__ 指向父类,表示构造函数的继承
子类的prototype.__proto__指向父类的prototype属性, 表示方法的继承
子类实例的__proto__.__proto__指向父类实例的__proto__属性



作者:daisimin7
链接:http://www.jianshu.com/p/b1a07c84c8eb
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
发布了1 篇原创文章 · 获赞 1 · 访问量 1万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章