摘要:所以自己動手用重新實現了一遍里面的設計模式,算是對其的鞏固,也算是與大家一起來研究探討語法的一些最佳實踐。
前言
最近在回顧設計模式方式的知識,重新翻閱了《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(" ")); //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)跑通。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/92322.html
摘要:高質量特性面向對象,無類,原型可維護的代碼可讀一致可預測看起來像是同一個人寫的文檔減少全局對象,傳參訪問全局對象單模式,忘記時的副作用顯式聲明的全局變量無法用刪除不擴充內置原型模式每個和對齊這里不考慮花括號相關的縮進規則每個中的代碼整齊縮進 高質量Javascript Javascript特性:面向對象,無類,原型 可維護的代碼(可讀;一致;可預測;看起來像是同一個人寫的;文檔) 減...
摘要:此處的構造函數使用的形式添加新屬性,但實際上新屬性的添加有四種方式,除去這一種,還有三種方括號語法,方法方法此處舉的是原文中的例子,若要使用,可參考原文。 參考書籍Learning Javascript Design Patterns 一、設計模式概述與應用場景 首先引用原書的一段話: Patterns are proven solutions: They provide solid ...
摘要:在可遍歷的量中使用數組模型數組解構使用一個迭代器來獲取數據源中的元素。所以,數組解構能夠在上工作的迭代器總是按照元素插入的順序將元素返回,所以上述的解構返回的結果總是相同的。 解構賦值(destructuring assignment)語法是一個Javascript表達式,這種語法能夠更方便的提取出 Object 或者 Array 中的數據。這種語法可以在接受提取的數據的地方使用,比如...
摘要:現在讓我們設置溫度值并將其增加減少幾次小結在中,單例模式根據是否懶漢模式餓漢模式以及是否線程安全,分為很多種實現方式。參考設計模式與開發實踐設計模式 Back in 1994, a book was authored by Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides that discusses 23 desg...
摘要:盡管可以讓代碼更加簡潔易讀,但對于只熟悉回調函數的人來說,可能對此還是會有所懷疑。始終避免在或使用回調函數,否則會吞噬任何后續的錯誤,將其作為鏈的一部分。然而,使用回調函數,使用所謂的,即第一個參數是一個錯誤回調變得很常見。 原文:ES6 Promises: Patterns and Anti-Patterns作者:Bobby Brennan 當幾年前,第一次使用 NodeJS 的時候...
閱讀 1378·2021-09-26 09:55
閱讀 1917·2019-08-30 12:45
閱讀 1055·2019-08-29 11:20
閱讀 3555·2019-08-26 11:33
閱讀 3412·2019-08-26 10:55
閱讀 1685·2019-08-23 17:54
閱讀 2382·2019-08-23 15:55
閱讀 2341·2019-08-23 14:23