getElementById
->
get element by id
昨天(2019年4月28日周日)我首次使用 状态机 实现了一个将 英文大小写混拼字符串转换为多个单词的任务.
eg: getElementById 拆分出: get element by id.
当时使用的是if-else感觉很是比较复杂的.
今天在其基础上 复习和学习了 状态机的玩法.特别是表格数组 - 状态表法在具体实现上的使用.
第一种是 比较推荐的: 当前状态 和 事件 作为坐标.
交叉处是 函数 和下一个状态.
参考文档:https://blog.csdn.net/younggift/article/details/35848677
https://yunjianfei.iteye.com/blog/2061790
优点是:增加状态和事件都很方便维护.
查两张表:
现态: 横坐标
转移条件: 纵坐标
交叉数据: 新的状态
如图:
(我的图是横/纵坐标反了)
key-value表:
key:是状态.
value:是触发的处理(动作)函数.
{
‘状态1’:callback1,
‘状态2’:callback2
}
/**
* @description 测试状态表
*
* 状态
* 事件
*
*/
const STA_START = 0
const STA_U1 = 1
const STA_U2 = 2
const STA_L1 = 3
const STA_END = 99
const STA_ERROR = 100
// 事件 ,条件 condition
const COND = {
upper: 0,
lower: 1,
end: 9,
}
let state_transition_table = [
//事件: upper,lower,end
[STA_U1, STA_L1, STA_END], //START
[STA_U2, STA_L1, STA_END], //U1
[STA_U2, STA_L1, STA_END], //U2
[STA_U1, STA_L1, STA_END], //L1
]
// 转移到u1
function do_u1() {
console.log('u1')
}
function do_u2() {
console.log('u2')
}
function do_l1() {
console.log('l1')
}
/**
* 状态动作表
* 根据状态查找:对应的动作回调
*/
let state_action_table = { // JS竟然会将标识符 转换为 字符串...,所以不能使用 STA_U1:do_u1
1: do_u1,
2: do_u2,
3: do_l1,
}
// 当前状态
let m_statu = STA_START;
/**
* @description {获取状态迁移}
* @param {条件} condition
* @param {当前状态} now_statu
* @returns {新状态}
*/
function get_state_transition(condition, now_statu = m_statu) {
return state_transition_table[now_statu][condition];
}
/**
* 执行迁移状态,会修改现在状态,并执行迁移函数
* @param {迁移到的状态} statu
*/
function move_status(statu) {
console.log(state_action_table)
let callback = state_action_table[statu];
m_statu = statu; //改状态 ... ...
if (callback == undefined) {
throw ('无处理函数')
}
callback();
}
while (true) {
//继续获取下一个条件
//getNextCondition()
let new_statu = get_state_transition(COND.lower); // 获取下一个状态
console.log(new_statu)
if (new_statu == STA_END) {
break;
}
move_status(new_statu); // 迁移状态并触执行相关动作
}
状态机的核心是两个表:
function(条件/*新字符etc.*/,现态/*当前判断是大小写*/) = 新态;
真正的跳出是在第二步,这样就避免了:
分成两张表的好处在于不混乱.
2019年9月25日