"ES6 Standard Introduction (Ruan Yifeng) 3rd Edition" reading notes

As long as a data structure is deployed with Symbol.iteratorattributes, it is considered to have an iterator interface, and for...ofits members can be traversed using loops. In other words, for...ofthe Symbol.iteratormethod of the data structure is called inside the loop .

// yield语句遍历完全二叉树
// 下面是二叉树的构造函数,
// 3个参数分别是左树、当前节点和右树
function Tree(left, label, right){
	this.left = left;
	this.label = label;
	this.right = right;
}
// 下面是中序(inorder)遍历函数。
// 由于返回的是一个便利器,所以要用generator函数。
// 函数体内采用递归算法,所以左树和右树要用yield*遍历
function* inorder(t){
	if(t){
		yield* inorder(t.left);
		yield t.label;
		yield* inorder(t.right);
	}
}
// 下面生成二叉树
function make(array){
	// 判断是否为叶节点
	if(array.length == 1) return new Tree(null,array[0], null);
	return new Tree(make(array[0]), array[1], make(array[2]));
}
let tree = make([[['a'], 'b', ['c']], 'd', [['e'], 'f', ['g']]]);
// 遍历二叉树
var result = [];
for(let node of inorder(tree)){
	result.push(node);
}
console.log(result);
var clock = function* (){
	while(true){
		console.log('Tick!');
		yield;
		console.log('Tock!');
		yield;
	}
}
clock();

// 由于JavaScript是单线程语言,只能保持一个调用栈。引入协程以后,
// 每个任务可以保持自己的调用栈。这样做的最大好书,就是抛出错误的时候,
// 可以找到原始的调用栈。不至于像异步操作的回调函数那样,
// 一旦出错原始的调用栈早就结束。Generator函数是对协程的实现,但属于不完全实现。
// Generator函数可以改善代码运行流程
function* longRunningTask(value){
	try{
		var value2 = yield step1(value);
		var value3 = yield step2(value2);
		var value4 = yield step3(value3);
		var value5 = yield step4(value4);
		// Do something with value4
	} catch(e) {
		// handle any error from step1 through step4
	}
}
// 使用一个函数按次序自动执行所有步骤
scheduler(longRunningTask(initalValue));
function scheduler(task){
	var taskobj = task.next(task.value);
	// 如果Generator函数未结束,就继续调用
	if(!taskObj.done){
		task.value = taskObj.value;
		scheduler(task);
	}
}
// Promise的最大问题是冗余,原来的任务被Promise包装之后,
// 无论什么操作,一眼看去都是很多then的堆积,原来的语义变得很不清楚。	协程:多个线程互相协作,完成异步任务。
// next返回值的value属性石Generate函数向外输出数据;
// next方法还可以接受参数,向Generator函数体内输入数据
function* gen(x){
	var y = yield x + 2;
	return y;
}
var g = gen(1);
g.next() //{value:3, done: false}
g.next(2) //{value:2, done: true}
// 传名调用
function f(m){
	return m*2;
}
f(x+5);
// JavaScript语言是传值调用,
// 手动执行其实就是用then方法层层添加回调函数 手写自动执行器
function run(gen){
	var g = gen();
	function next(data){
		var result = g.next(data);
		if(result.done){
			return result.value;
		}
		result.value.then(function(data){
			next(data);
		});
	}
	next();
}
// Node提供Stream模式读写数据,特点是一次只处理数据的一部分,
// 数据被分成一块一块依次处理,就好像“数据流”一样。
// async函数用一句话来说,它就是Generator函数的语法糖。
// async函数对Generator函数的改进体现在4点:1、自带执行器;2、更好的语义;3
// 更广的适用性:async函数的await命令后面,
// 可以是Promise对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作);
// 4、返回值是Promise:async函数完全可以看作由多个异步操作包装成的一个Promise对象,
// 而await命令就是内部then命令的语法糖。
// 
// async指定多少毫秒后输出一个值
function timeout(ms){
	return new Promise((resolve) =>{
		setTimeout(resolve, ms);
	});
}
async function aysncPrice(value, ms){
	await timeout(ms);
	console.log(value);
}
asyncPrint('hello world', 50);
// 如果函数返回多个值,优先使用对象的解构赋值,而不是数组的解构赋值。
// 这样便于以后添加返回值,以及更改返回值的顺序
// bad
function processInput(input){
	return [left, right, top, bottom];
}
// good
function processInput(input){
	return {left, right, top, bottom};
}
const {left, right} = processInput(input);
// bad
[1,2,3].map(function(x){
	return x*x;
});
// good
[1,2,3].map((x)=>{
	return x*x;
});
// best
[1,2,3].map(x=>x*x);
// 箭头函数取代Function.prototype.bind,不再用self/_this/that绑定this
// bad
// const self = this;
const boundMethod = function(...params){
	return method.apply(self,params);
}
// acceptable
const boundMethod = method.bind(this);
// best
const boundMethod = (...params) => method.apply(this, params);

//  多个await命令后面的异步操作如果不存在继发关系,最好让它们同时触发
// 写法一
let [foo, bar] =await Promise.all([getFoo(), getBar()]);
// 写法二
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;
// 上面两种写法中,getFoo和getBar都是同时触发,这样就会缩短程序的执行时间
// async函数的实现原理就是将Generator函数和自动执行器包装在一个函数里
async function fn(args){
  // ...
}
// 等同于
function fn(args){
  return spawn(function* (){
    // ...
  });
}
// spawn函数就是自动执行器
function spawn(genF){
  return new Promise(function(resolve, reject){
    var gen = genF();
    function step(nextF){
      try{
        var next = nextF();
      }catch(e){
        return reject(e);
      }
      if(next.done){
        return resolve(next.value);
      }
      Promise.resolve(next.value).then(function(v){
        step(function(){
          return gen.next(v);
        }),function(e){
          step(function(){
            return gen.throw(e);
          });
        }
      })
    }
    step(function(){
      return gen.next(undefined);
    })
  })
}
// aysnc实现:假如某个DOM元素上面,部署了一系列的动画,前一个动画结束,才能开始后一个。
// 如果当中与一个动画出错,就不再继续执行,而返回上一个成功执行的动画的返回值。
async function chainAnimationsAsync(elem, animations){
  var ret = null;
  try{
    for(var anim of animations){
      ret = await anim(elem);
    }
  }catch(e){
    /* 忽略错误,继续执行 */
  }
  return ret;
}
// for await...of循环用于遍历异步的Iterator接口
async function f(){
  for await (const x of createAsyncIterable(['a','b'])){
    console.log(x);
  }
}
// 基本上,ES6中的class可以看作只是一个语法糖,它的绝大部分功能,ES5都可以做到,新的class写法只是让对象原型的写法更加清晰,更像面向对象编程的语法而已。
// Symbol值,达到私有方法和私有属性的效果
const bar = Symbol('bar');
const snaf = Symbol('snaf');
export default class myClass{
  // 公有方法
  foo(baz){
    this[bar](baz);
  }
  // 私有方法
  [bar](baz){
    return this[snaf] = baz;
  }
}
// 类的方法内部如果含有this,它将默认指向类的实例。一旦单独使用该方法,很可能会报错。
// 父类的静态方法可以被子类继承
class Foo {
  static classMethod(){
    return 'hello';
  }
}
class Bar extends Foo{}
Bar.classMethod() // 'hello
// ES6可以自定义原生数据结构(比如Array、String等)的子类,这是ES5无法做到的。
class MyArray extends Array{
  constructor(...args){
    super(...args);
  }
}
var arr = new MyArray();
arr[0] = 12;
arr.length // 1
arr.length = 0;
arr[0] // undefined
// 装饰器改写React与Redux库结合代码
class MyReactComponent extends React.Component{}
export default connect(mapStateToProps, mapDispatchToProps)(MyReactComponent);
// 可改写成如下
@connect(mapStateToProps, mapDispatchToProps)
export defulat class MyReactComponent extends React.Component{}
// 由于存在函数提升,修饰器不能用于函数。类是不会提升的,所以就没有这方面的问题。
// 将Mixin写成一个修饰器
export function mixins(...list){
  return function(target){
    Object.assign(target.prototype, ...list);
  }
}
import {mixins} from './mixins';
const Foo = {
  foo(){
    console.log('foo')
  }
};
@mixins(Foo)
class MyClass{}
let obj = new MyClass();
obj.foo() // "foo"
// CommonJs模块就是对象,输入时必须查找对象属性
// 如下代码只有运行时才能得到这个对象,称为"运行时加载",导致完全没办法在编译时进行"静态优化"
let {stat,exists,readFile} = require('fs');
// ES6"编译时加载"或者叫静态加载
import {stat,exists,readFile} from 'fs';
import { Socket } from 'dgram';
// 严格模式不能使用前缀0表示八进制数,否则报错
// 接口改名
export {foo as myFoo} from "my_module";
// defer是“渲染完再执行”,async是“下载完就执行”。
// CommonJs模块输出的是值的肤质,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。
// ES6模块不会缓存结果,而是动态地去被加载的模块取值,并且斌梁总是绑定其所在的模块。
// 总是用Class取代需要prototype的操作。因为Class的写法更简洁,更易于理解。
// bad
function Queue(contents = []){
  const value = this._queue[0];
  this._queue.splice(0,1);
  return value;
}
// good
class Queue{
  constructor(contents = []){
    this._queue = [...contents];
  }
  pop(){
    const value = this._queue[0];
    this._queue.splice(0,1);
    return value;
  }
}
// .eslintrc
{
  "extends": "eslint-config-airbnb"
}
// WebGL,就是浏览器与显卡之间的通信接口,为了满足JavaScript与显卡之间大量、实时的数据交换。
// 它们自建的数据通信必须是二进制的,而不能是传统的文本格式。
// 二进制数组并不是真正的数组,而是类似数组的对象
// TypedArray视图与DataView视图的一个区别是,它不是一个构造函数,而是一组构造函数,代表不同的数据格式。TypedArray的数组成员都是同一个数据类型,而DataView的数组成员可以是不同的数据类型。
// 网页canvas元素输出的二进制像素数据就是TypedArray数组
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
var imageData = ctx.getImageData(0,0,canvas.clientWidth,canvas.height);
var unit8ClampedArray = imgaeData.data;
// Websocket可以通过ArrayBuffer发送或接收二级制数据
var websocket = new WebSocket('ws://127.0.0.1:8081');
socket.binaryType = 'arraybuffer';
// Wait until socket is open
socket.addEventListener('open', function(event){
  // send binary data
  var typedArray = new Uint8Array(4);
  socket.send(typedArray.buffer);
});
// Receive binary data
socket.addEventListener('message', function(event){
  var arrayBuffer = event.data;
  // ...
});

 

Guess you like

Origin blog.csdn.net/taozi550185271/article/details/106339165
Recommended