觀察者模式其實在平常編碼中常常遇到,好比DOM的事件監聽,代碼以下es6
function clickHandler(event) { console.log('user click!'); } document.body.addEventListener('click', clickHandler)
簡而言之:觀察者模式就如同上代碼,有一個事件源‘dom 的click事件’ 也就是abservable,有一個觀察者abserver clickHandler函數,有一個訂閱機制(addEventLister),當dom的click事件觸發時候,會經過訂閱機制通知abserver 執行函數clickHandler函數。數組
下面是構建一個觀察者模式的簡單例子dom
function Producer() { // 這個 if 只是避免使用者不當心把 Producer 看成函式來調用 if(!(this instanceof Producer)) { throw new Error('請用 new Producer()!'); // 仿 ES6 行爲可用: throw new Error('Class constructor Producer cannot be invoked without 'new'') } this.listeners = []; } // 加入監聽的方法 Producer.prototype.addListener = function(listener) { if(typeof listener === 'function') { this.listeners.push(listener) } else { throw new Error('listener 必須是 function') } } // 移除監聽的方法 Producer.prototype.removeListener = function(listener) { this.listeners.splice(this.listeners.indexOf(listener), 1) } // 發送通知的方法 Producer.prototype.notify = function(message) { this.listeners.forEach(listener => { listener(message); }) }
接下來創建實例函數
var egghead = new Producer(); // new 出一個 Producer 實例叫 egghead function listener1(message) { console.log(message + 'from listener1'); } function listener2(message) { console.log(message + 'from listener2'); } egghead.addListener(listener1); // 註冊監聽 egghead.addListener(listener2); egghead.notify('A new course!!') // 當某件事情方法時,執行 //a new course!! from listener1 //a new course!! from listener2
Iterator 是一個物件,它的就像是一個指針(pointer),指向一個資料結構併產生一個序列(sequence),這個序列會有資料結構中的全部元素(element)。
迭代者(Iterator,也稱爲「迭代器」)指的是可以遍歷⼀個數據集合的對象,由於數據集合的實現⽅式不少,能夠是⼀個數組,也能夠是⼀個樹形結構,也能夠是⼀個單向鏈表……迭代器的做⽤就是提供⼀個通⽤的接口,讓使⽤者徹底不⽤關⼼這個數據集合的具體實現⽅式。this
本身實現簡單的迭代器編碼
function IteratorFromArray(arr) { if(!(this instanceof IteratorFromArray)) { throw new Error('請用 new IteratorFromArray()!'); } this._array = arr; this._cursor = 0; } IteratorFromArray.prototype.next = function() { return this._cursor < this._array.length ? { value: this._array[this._cursor++], done: false } : { done: true }; }
生成器是一種返回迭代器的函數,經過function關鍵字後的星號(*)來表示,函數中會用到新的關鍵字yield。星號能夠緊挨着function關鍵字,也能夠在中間添加一個空格prototype
// 生成器 function *createIterator() { yield 1; yield 2; yield 3; } // 生成器能像正規函數那樣被調用,但會返回一個迭代器 let iterator = createIterator(); console.log(iterator.next().value); // 1 console.log(iterator.next().value); // 2 console.log(iterator.next().value); // 3 function *createIterator(items) { for (let i = 0; i < items.length; i++) { yield items[i]; } } let iterator = createIterator([1, 2, 3]); console.log(iterator.next()); // "{ value: 1, done: false }" console.log(iterator.next()); // "{ value: 2, done: false }" console.log(iterator.next()); // "{ value: 3, done: false }" console.log(iterator.next()); // "{ value: undefined, done: true }" // 以後的全部調用 console.log(iterator.next()); // "{ value: undefined, done: true }"
Observable 其實就是這兩個 Pattern 思想的結合,Observable 具有生產者推送資料的特性,同時能像序列,擁有序列處理資料的方法(map, filter...)!指針
更簡單的來講,Observable 就像是一個序列,裡面的元素會隨著時間推送。code