用ES6重写《JavaScript Patterns》中的设想形式

媒介

最近在回忆设想形式体式格局的学问,从新翻阅了《JavaScript形式》(个人觉得也算是一本小有名气的书了哈)一书,读时总有感想:期近将到来的ES6的大潮下,书中的很多形式的代码可用ES6的语法更加文雅简约的完成,而另一些形式,则已被ES6原生支撑,如模块形式(99页)。所以本身动手用ES6从新完成了一遍内里的设想形式,算是对其的稳固,也算是与人人一起来研讨讨论ES6语法的一些最好实践。

目次

(以下一切例子的原型均为《JavaScript形式》一书里“设想形式”章节中的示例)

代码repo地点,迎接star,迎接follow。

完成

单例形式

重要改变成运用了class的写法,使对象原型的写法更加清楚,更整齐:

js'use strict';
let __instance = (function () {
  let instance;
  return (newInstance) => {
    if (newInstance) instance = newInstance;
    return instance;
  }
}());

class Universe {
  constructor() {
    if (__instance()) return __instance();
    //按本身需求实例化
    this.foo = 'bar';
    __instance(this);
  }
}

let u1 = new Universe();
let u2 = new Universe();

console.log(u1.foo); //'bar'
console.log(u1 === u2); //true

迭代器形式

ES6原生供应的Iterator接口就是为这而生的啊,运用胖箭头函数写匿名函数(还顺带绑定了上下文,舒舒服服):

js'use strict';
let agg = {
  data: [1, 2, 3, 4, 5],
  [Symbol.iterator](){
    let index = 0;
    return {
      next: () => {
        if (index < this.data.length) return {value: this.data[index++], done: false};
        return {value: undefined, done: true};
      },
      hasNext: () => index < this.data.length,
      rewind: () => index = 0,
      current: () => {
        index -= 1;
        if (index < this.data.length) return {value: this.data[index++], done: false};
        return {value: undefined, done: true};
      }
    }
  }
};

let iter = agg[Symbol.iterator]();
console.log(iter.next()); // { value: 1, done: false }
console.log(iter.next()); // { value: 2, done: false }
console.log(iter.current());// { value: 2, done: false }
console.log(iter.hasNext());// true
console.log(iter.rewind()); // rewind!
console.log(iter.next()); // { value: 1, done: false }

// for...of
for (let ele of agg) {
  console.log(ele);
}

工场形式

个人觉得变化比较不大的一个:

js'use strict';
class CarMaker {
  constructor() {
    this.doors = 0;
  }

  drive() {
    console.log(`jaja, i have ${this.doors} doors`);
  }

  static factory(type) {
    return new CarMaker[type]();
  }
}

CarMaker.Compact = class Compact extends CarMaker {
  constructor() {
    super();
    this.doors = 4;
  }
};

CarMaker.factory('Compact').drive(); // 'jaja, i have 4 doors'

装潢者形式

for...of轮回,新时代的for (var i = 0 ; i < arr.length ; i++)? :

js'use strict';
class Sale {
  constructor(price) {
    [this.decoratorsList, this.price] = [[], price];
  }

  decorate(decorator) {
    if (!Sale[decorator]) throw new Error(`decorator not exist: ${decorator}`);
    this.decoratorsList.push(Sale[decorator]);
  }

  getPrice() {
    for (let decorator of this.decoratorsList) {
      this.price = decorator(this.price);
    }
    return this.price.toFixed(2);
  }

  static quebec(price) {
    return price + price * 7.5 / 100;
  }

  static fedtax(price) {
    return price + price * 5 / 100;
  }
}

let sale = new Sale(100);
sale.decorate('fedtax');
sale.decorate('quebec');
console.log(sale.getPrice()); //112.88

战略形式

关于传统的键值对,运用Map来替代对象(数组)来构造,觉得带来得是更好的语义和更轻易的遍历:

js'use strict';
let data = new Map([['first_name', 'Super'], ['last_name', 'Man'], ['age', 'unknown'], ['username', 'o_O']]);
let config = new Map([['first_name', 'isNonEmpty'], ['age', 'isNumber'], ['username', 'isAlphaNum']]);

class Checker {
  constructor(check, instructions) {
    [this.check, this.instructions] = [check, instructions];
  }
}

class Validator {
  constructor(config) {
    [this.config, this.messages] = [config, []];
  }

  validate(data) {
    for (let [k, v] of data.entries()) {
      let type = this.config.get(k);
      let checker = Validator[type];
      if (!type) continue;
      if (!checker) throw new Error(`No handler to validate type ${type}`);
      let result = checker.check(v);
      if (!result) this.messages.push(checker.instructions + ` **${v}**`);
    }
  }

  hasError() {
    return this.messages.length !== 0;
  }
}

Validator.isNumber = new Checker((val) => !isNaN(val), 'the value can only be a valid number');
Validator.isNonEmpty = new Checker((val) => val !== "", 'the value can not be empty');
Validator.isAlphaNum = new Checker((val) => !/^a-z0-9/i.test(val), 'the value can not have special symbols');

let validator = new Validator(config);
validator.validate(data);
console.log(validator.messages.join('\n')); //the value can only be a valid number **unknown**

表面形式

这个几乎没啥好变的。。。:

js'use strict';
let nextTick = (global.setImmediate == undefined) ? process.nextTick : global.setImmediate;

代办形式

应用extends关键字来取得父类中的要领援用以及和父类雷同的类接口:

js'use strict';
class Real {
  doSomething() {
    console.log('do something...');
  }
}

class Proxy extends Real {
  constructor() {
    super();
  }

  doSomething() {
    setTimeout(super.doSomething, 1000 * 3);
  }
}

new Proxy().doSomething(); //after 3s ,do something...

定阅/宣布形式

被Node原生的Events模块所支撑,一样连系默许参数,for…of遍历等特征,代码的削减以及可读性的增添都是可观的:

js'use strict';
class Event {
  constructor() {
    this.subscribers = new Map([['any', []]]);
  }

  on(fn, type = 'any') {
    let subs = this.subscribers;
    if (!subs.get(type)) return subs.set(type, [fn]);
    subs.set(type, (subs.get(type).push(fn)));
  }

  emit(content, type = 'any') {
    for (let fn of this.subscribers.get(type)) {
      fn(content);
    }
  }
}

let event = new Event();

event.on((content) => console.log(`get published content: ${content}`), 'myEvent');
event.emit('jaja', 'myEvent'); //get published content: jaja

末了

以上一切代码都可经由过程Babel跑通,90%以上的代码可被当前版本的io.js(v2.0.2)跑通。

    原文作者:菜菜蔡伟
    原文地址: https://segmentfault.com/a/1190000002800554
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞