- 下面的狀態機選擇通過Function.prototype.call方法直接把請求委托給某個字面量對象來執行。
var light = function () { this.currstate = FSM.off; this.button = null; }; light.prototype.init = function () { var button = document.createElement('button'); self = this; button.innerHTML = '已關燈'; this.button = document.body.appendChild(button); this.button.onclick = function () { self.currstate.buttonWasPressed.call(self); }; }; var FSM = { off: { buttonWasPressed: function () { console.log('關燈'); this.button.innerHTML = '下一次按我是開燈'; this.currstate = FSM.on; } }, on: { buttonWasPressed: function () { console.log('開燈'); this.button.innerHTML = '下一次按我是關燈'; this.currstate = FSM.off; } } }; var light = new light(); light.init();
- 下面利用delegate函數來重寫一遍這個狀態機
- 這是面向對象和閉包互換的一個例子。前者將變量保存為對象的屬性,后者將變量封閉在閉包形成的環境中:
var delegate = function (client, delegation) { return { buttonWasPressed: function () { return delegation.buttonWasPressed.apply(client, arguments); } }; }; var light = function () { this.offstate = delegate(this, FSM.off); this.onstate = delegate(this, FSM.on); this.currstate = FSM.off; this.button = null; }; light.prototype.init = function () { var button = document.createElement('button'); self = this; button.innerHTML = '已關燈'; this.button = document.body.appendChild(button); this.button.onclick = function () { self.currstate.buttonWasPressed.call(self); }; }; var FSM = { off: { buttonWasPressed: function () { console.log('關燈'); this.button.innerHTML = '下一次按我是開燈'; this.currstate = this.onstate; } }, on: { buttonWasPressed: function () { console.log('開燈'); this.button.innerHTML = '下一次按我是關燈'; this.currstate = this.offstate; } } }; var light = new light(); light.init();
Github上有另外一種方式:
