大家好,我是IT修真院北京總院第24期的學(xué)員,一枚正直純潔善良的web程序員
今天給大家分享一下,修真院官網(wǎng)js任務(wù)3,深度思考中的知識(shí)點(diǎn)——什么是有限狀態(tài)機(jī)??
1.背景介紹
什么是有限狀態(tài)機(jī)?
有限狀態(tài)機(jī),(英語(yǔ):Finite-state machine, FSM),又稱(chēng)有限狀態(tài)自動(dòng)機(jī),簡(jiǎn)稱(chēng)狀態(tài)機(jī),是表示有限個(gè)狀態(tài)以及在這些狀態(tài)之間的轉(zhuǎn)移和動(dòng)作等行為的數(shù)學(xué)模型。
有限狀態(tài)機(jī)一般都有以下特點(diǎn):
(1)可以用狀態(tài)來(lái)描述事物,并且任一時(shí)刻,事物總是處于一種狀態(tài);
(2)事物擁有的狀態(tài)總數(shù)是有限的;
(3)通過(guò)觸發(fā)事物的某些行為,可以導(dǎo)致事物從一種狀態(tài)過(guò)渡到另一種狀態(tài);
(4)事物狀態(tài)變化是有規(guī)則的,A狀態(tài)可以變換到B,B可以變換到C,A卻不一定能變換到C;
(5)同一種行為,可以將事物從多種狀態(tài)變成同種狀態(tài),但是不能從同種狀態(tài)變成多種狀態(tài)。
2.知識(shí)剖析
在js中,新建一個(gè)對(duì)象,用這個(gè)對(duì)象的屬性來(lái)模擬元素的狀態(tài),用這個(gè)對(duì)象的方法模擬元素在不同狀態(tài)的轉(zhuǎn)變,那么這個(gè)對(duì)象就是一個(gè)有限狀態(tài)機(jī)。
是否可用有限狀態(tài)機(jī)來(lái)描述,卻決于:
當(dāng)前狀態(tài)確定,有限個(gè)狀態(tài),響應(yīng)事件,在不同狀態(tài)間有規(guī)律的轉(zhuǎn)變。
它對(duì)JavaScript的意義在于,很多對(duì)象可以寫(xiě)成有限狀態(tài)機(jī)。
舉例來(lái)說(shuō),網(wǎng)頁(yè)上有一個(gè)菜單元素。鼠標(biāo)懸停的時(shí)候,菜單顯示;鼠標(biāo)移開(kāi)的時(shí)候,菜單隱藏。如果使用有限狀態(tài)機(jī)描述,就是這個(gè)菜單只有兩種狀態(tài)(顯示和隱藏),鼠標(biāo)會(huì)引發(fā)狀態(tài)轉(zhuǎn)變。
var menu = {
// 當(dāng)前狀態(tài)
currentState: 'hide',
// 綁定事件
initialize: function() {
var self = this;
self.on("hover", self.transition);
},
// 狀態(tài)轉(zhuǎn)換
transition: function(event){
switch(this.currentState) {
case "hide":
this.currentState = 'show';
doSomething();
break;
case "show":
this.currentState = 'hide';
doSomething();
break;
default:
console.log('Invalid State!');
break;
}
}
};
可以看到,有限狀態(tài)機(jī)的寫(xiě)法,邏輯清晰,表達(dá)力強(qiáng),有利于封裝事件。一個(gè)對(duì)象的狀態(tài)越多、發(fā)生的事件越多,就越適合采用有限狀態(tài)機(jī)的寫(xiě)法。
另外,JavaScript語(yǔ)言是一種異步操作特別多的語(yǔ)言,常用的解決方法是指定回調(diào)函數(shù),但這樣會(huì)造成代碼結(jié)構(gòu)混亂、難以測(cè)試和除錯(cuò)等問(wèn)題。有限狀態(tài)機(jī)提供了更好的辦法:把異步操作與對(duì)象的狀態(tài)改變掛鉤,當(dāng)異步操作結(jié)束的時(shí)候,發(fā)生相應(yīng)的狀態(tài)改變,由此再觸發(fā)其他操作。這要比回調(diào)函數(shù)、事件監(jiān)聽(tīng)、發(fā)布/訂閱等解決方案,在邏輯上更合理,更易于降低代碼的復(fù)雜度。
3.常見(jiàn)問(wèn)題
有限狀態(tài)機(jī)有哪些應(yīng)用場(chǎng)景?
4.解決方案
滿(mǎn)足3點(diǎn)即可用:所需狀態(tài)確定,有事件觸發(fā)轉(zhuǎn)變狀態(tài),總狀態(tài)有限且轉(zhuǎn)變有規(guī)律。
頁(yè)面可用有限狀態(tài)機(jī)的元素較多且有規(guī)律時(shí)可用:例如:開(kāi)關(guān)按鈕,下拉菜單,
Javascript Finite State Machine 函數(shù)庫(kù)
//交通信號(hào)燈的模型描述:
var fsm = StateMachine.create({
initial: 'green',
events: [
{ name: 'warn',? from: 'green',? to: 'yellow' },
{ name: 'stop', from: 'yellow', to: 'red' },
{ name: 'ready',? from: 'red',? ? to: 'yellow' },
{ name: 'go', from: 'yellow', to: 'green' }
],
callbacks:{
callback1:function(){...},
callback2:function(){...},
...
},
error: function(){...}
});
initial選項(xiàng)用來(lái)表示fsm對(duì)象的初始狀態(tài),events選項(xiàng)用來(lái)描述fsm對(duì)象所有狀態(tài)的變化規(guī)則,每一種變化規(guī)則對(duì)應(yīng)一種行為。create方法為實(shí)例的每一種行為都添加了一個(gè)方法,調(diào)用這個(gè)方法就相當(dāng)于觸發(fā)對(duì)象的某種行為,當(dāng)對(duì)象行為發(fā)生時(shí),對(duì)象的狀態(tài)就可以發(fā)生變化。如以上例子創(chuàng)建的實(shí)例將擁有如下行為方法: fsm.warn() : 調(diào)用該方法,實(shí)例狀態(tài)將從'green'變?yōu)?yellow' fsm.stop() : 調(diào)用該方法,實(shí)例狀態(tài)將從'yellow'變?yōu)?red' fsm.ready() : 調(diào)用該方法,實(shí)例狀態(tài)將從'red'變?yōu)?yellow' fsm.go() : 調(diào)用該方法,實(shí)例狀態(tài)將從'yellow'變?yōu)?green'
這些方法是StateMachine根據(jù)create時(shí)配置的events規(guī)則自動(dòng)創(chuàng)建的,方法名跟events規(guī)則里面的name屬性對(duì)應(yīng),events規(guī)則里面有幾個(gè)不重復(fù)的name,就會(huì)添加幾個(gè)行為方法。同時(shí)為了方便使用,它還添加了如下成員來(lái)判斷和控制實(shí)例的狀態(tài)和行為: fsm.current - 返回實(shí)例當(dāng)前的狀態(tài) fsm.is(state) - 如果傳入的state是實(shí)例當(dāng)前狀態(tài)就返回true fsm.can(eventName) - 如果傳入的eventName在實(shí)例當(dāng)前狀態(tài)能夠被觸發(fā)就返回true fsm.cannot(eventName) - 如果傳入的eventName在實(shí)例當(dāng)前狀態(tài)不能被觸發(fā)就返回true fsm.transitions() - 以數(shù)組的形式返回實(shí)例當(dāng)前狀態(tài)下能夠被觸發(fā)的行為列表
Javascript Finite State Machine允許為每個(gè)事件指定兩個(gè)回調(diào)函數(shù),以warn事件為例: onbeforewarn:在warn事件發(fā)生之前觸發(fā) onafterwarn(可簡(jiǎn)寫(xiě)成onwarn) :在warn事件發(fā)生之后觸發(fā)。 同時(shí),它也允許為每個(gè)狀態(tài)指定兩個(gè)回調(diào)函數(shù),以green狀態(tài)為例: onleavegreen :在離開(kāi)green狀態(tài)時(shí)觸發(fā) onentergreen(可簡(jiǎn)寫(xiě)成ongreen) :在進(jìn)入green狀態(tài)時(shí)觸發(fā)。
假定warn事件使得狀態(tài)從green變?yōu)閥ellow,上面四類(lèi)回調(diào)函數(shù)的發(fā)生順序?yàn)椋?onbeforewarn → onleavegreen → onenteryellow → onafterwarn。 還為所有的事件和狀態(tài)指定通用的回調(diào)函數(shù): onbeforeevent :任一事件發(fā)生之前觸發(fā) onleavestate :離開(kāi)任一狀態(tài)時(shí)觸發(fā) onenterstate :進(jìn)入任一狀態(tài)時(shí)觸發(fā) onafterevent :任一事件結(jié)束后觸發(fā)
以{ name: 'warn', from: 'green', to: 'yellow' }為例,這八個(gè)回調(diào)函數(shù)順序?yàn)椋?onbeforewarn onbeforeevent onleavegreen onleavestate onenteryellow onenterstate onafterwarn onafterevent
5.編碼實(shí)戰(zhàn)
6.擴(kuò)展思考
有限狀態(tài)機(jī)通常在什么地方被用到?
大體上編程都是對(duì)現(xiàn)實(shí)的抽象,有效狀態(tài)機(jī)也不例外,當(dāng)邏輯里面有大量判斷需要轉(zhuǎn)換狀態(tài)時(shí),有限狀態(tài)機(jī)就有用處了,本質(zhì)上其是用查表法來(lái)把處理邏輯獨(dú)立到表中,從而可以用通用的代碼去處理任意復(fù)雜的狀態(tài)轉(zhuǎn)換。 具體場(chǎng)景有狀態(tài)超多的詞法分析(要識(shí)別各種關(guān)鍵字,運(yùn)算符等等),工控軟件中,有些機(jī)器的控制邏輯也可以用到,擴(kuò)展開(kāi)來(lái),任何復(fù)雜狀態(tài)邏輯的處理都可以
7.參考文獻(xiàn)
《javascript高級(jí)程序設(shè)計(jì)》
視頻鏈接? ? ?密碼: 85w1
感謝大家觀(guān)看
今天的分享就到這里啦,歡迎大家點(diǎn)贊、轉(zhuǎn)發(fā)、留言、拍磚~
技能樹(shù).IT修真院
“我們相信人人都可以成為一個(gè)工程師,現(xiàn)在開(kāi)始,找個(gè)師兄,帶你入門(mén),掌控自己學(xué)習(xí)的節(jié)奏,學(xué)習(xí)的路上不再迷茫”。
這里是技能樹(shù).IT修真院,成千上萬(wàn)的師兄在這里找到了自己的學(xué)習(xí)路線(xiàn),學(xué)習(xí)透明化,成長(zhǎng)可見(jiàn)化,師兄1對(duì)1免費(fèi)指導(dǎo)。快來(lái)與我一起學(xué)習(xí)吧~
我的邀請(qǐng)碼:12361358,或者你可以直接點(diǎn)擊此鏈接:http://www.jnshu.com/login/1/12361358