Javascript 交换机中的ES6模式匹配

Javascript 交换机中的ES6模式匹配,javascript,ecmascript-6,Javascript,Ecmascript 6,考虑以下代码段: if (msg.operation == 'create') { model.blocks.push(msg.block) drawBlock(msg.block); } else if (msg.operation == 'select' && msg.properties.snap == 'arbitrary') { doStuff(msg.properties.x, msg.properties.y); } else if (msg.opera

考虑以下代码段:

if (msg.operation == 'create') {
  model.blocks.push(msg.block)
  drawBlock(msg.block);
} else if (msg.operation == 'select' && msg.properties.snap == 'arbitrary') {
  doStuff(msg.properties.x, msg.properties.y);
} else if (msg.operation == 'unselect') {
  doOtherStuff(msg.properties.geometry);
}
有没有办法重构它,以便我可以在
msg
上进行模式匹配,类似于以下无效代码:

或者,如果没有丑陋的
if-then-else
链,在ES6中实现这一点的最惯用方法是什么


更新。假设这是一个过于简单的例子,可能不需要进行全面的模式匹配。但我们可以想象一个场景,匹配一个长AST的任意层次部分


TL;博士解构的强大功能,并伴随着自动检查是否可以执行此操作。

您可以编写这样的
匹配
函数,该函数(与箭头函数和对象解构结合使用时)与示例中的语法非常相似:

/**
*称为:
*匹配(对象,
*模式1,回调1,
*模式2,回拨2,
*     ...
*   );
**/
函数匹配(对象,…参数){
对于(设i=0;i+1对象[key]==模式[key]);
如果(等质量)
返回回调(对象);
}
}
// -------- //
const msg={operation:'create',block:17};
匹配(味精,
{operation:'create'},({block:b})=>{
console.log('create',b);
},
{operation:'select block'},({id:id})=>{
console.log('select-block',id);
},
{操作:'取消选择块'},({id:id})=>{
console.log('unselect-block',id);
}

);
您可以编写这样的
匹配
函数,该函数(与箭头函数和对象解构结合使用时)与示例中的语法非常相似:

/**
*称为:
*匹配(对象,
*模式1,回调1,
*模式2,回拨2,
*     ...
*   );
**/
函数匹配(对象,…参数){
对于(设i=0;i+1对象[key]==模式[key]);
如果(等质量)
返回回调(对象);
}
}
// -------- //
const msg={operation:'create',block:17};
匹配(味精,
{operation:'create'},({block:b})=>{
console.log('create',b);
},
{operation:'select block'},({id:id})=>{
console.log('select-block',id);
},
{操作:'取消选择块'},({id:id})=>{
console.log('unselect-block',id);
}
);当然,为什么不呢

函数匹配(对象){
this.case=(条件,fn)=>{
const doesMatch=Object.keys(条件)
.every(k=>条件[k]==对象[k])
if(doesMatch)fn(对象)
还这个
}
还这个
}
//使用示例:
const msg={operation:'create',block:5}
匹配(味精)
.case({operation:'create'},({block})=>console.log('create',block))
.case({operation:'select block'},({id})=>console.log('select-block',id))
.case({operation:'unselect block'},({id})=>console.log('unselect-block',id))
当然,为什么不呢

函数匹配(对象){
this.case=(条件,fn)=>{
const doesMatch=Object.keys(条件)
.every(k=>条件[k]==对象[k])
if(doesMatch)fn(对象)
还这个
}
还这个
}
//使用示例:
const msg={operation:'create',block:5}
匹配(味精)
.case({operation:'create'},({block})=>console.log('create',block))
.case({operation:'select block'},({id})=>console.log('select-block',id))

.case({operation:'unselect block'},({id})=>console.log('unselect-block',id))
您可以使用更高阶函数和分解结构分配来获得与模式匹配远程类似的内容:

const\u开关=f=>x=>f(x);
常量操作开关=_开关({操作,属性:{snap,x,y,geometry}})=>{
开关(操作){
案例“创建”:{
设x=true;
返回操作;
}
案例“选择”:{
设x=true;
如果(捕捉==“任意”){
返回操作+“”+捕捉;
}
打破
}
案例“取消选择”:{
设x=true;
返回操作;
}
}
});
const msg={operation:{operation:“select”,属性:{snap:{snap:“任意”,x:1,y:2,几何体:“foo”};
console.log(
操作开关(msg)//选择任意

);您可以使用更高阶的函数和解构赋值来获得与模式匹配远程相似的内容:

const\u开关=f=>x=>f(x);
常量操作开关=_开关({操作,属性:{snap,x,y,geometry}})=>{
开关(操作){
案例“创建”:{
设x=true;
返回操作;
}
案例“选择”:{
设x=true;
如果(捕捉==“任意”){
返回操作+“”+捕捉;
}
打破
}
案例“取消选择”:{
设x=true;
返回操作;
}
}
});
const msg={operation:“select”,属性:{snap:“任意”,x:1,y:2,几何体:“foo”};
console.log(
操作开关(msg)//选择任意

);
我认为@gunn在这方面做得不错,但我对他的代码的主要问题是,它依赖于一个副作用函数来产生结果–他的
匹配
函数没有有用的返回值

为了保持事物的纯洁,我将实施msg match { case { operation: 'create', block: b } => model.blocks.push(b); drawBlock(b); case { operation: 'select', properties: { snap: 'arbitrary', x: sx, y: sy } } => doStuff(sx, sy); case { operation: 'unselect', properties: { snap: 'specific' }, geometry: geom } => doOtherStuff(geom); }