模式匹配(pattern matching)是 lisp 、rust 、scala 、erlang 等语言中的常见语法,不过 JavaScript 始终未反对这个个性,尽管 tc39 早有相干的题案https://github.com/tc39/proposal-pattern-matching,不过目前停顿迟缓,遂研发了一个Babel插件用于在JavaScript中反对模式匹配的语法
babel-plugin-proposal-pattern-matching
装置
应用 npm:
npm install --save-dev babel-plugin-proposal-pattern-matching
设置
.babelrc
{ "plugins": ["babel-plugin-proposal-pattern-matching"]}
一些演示
简略应用
import match from 'babel-plugin-proposal-pattern-matching/match'const fib = n=>match(n)( (v=1)=>1, (v=2)=>1, _=>fib(_-1)+fib(_-2))console.log(fib(10))// -> 55
间接返回一个函数,配合函数式编程
import match from 'babel-plugin-proposal-pattern-matching/match'const fib = fnmatch( (v = 1) => 1, (v = 2) => 1, _ => fib(_ - 1) + fib(_ - 2))console.log(fib(10))// -> 55const arr = [1, 2, 3]console.log( arr.map( fnmatch( (v = 1) => 'one', (v = 2) => 'two', (v = 3) => 'three' ) ))// -> [ 'one', 'two', 'three' ]
数据类型判断
import { match , T} from 'babel-plugin-proposal-pattern-matching/match'const getType = item => match(item)( (v = T.number) => 'number', (v = T.string) => 'string', (v = T.nullish) => 'nullish', _ => `${_} undefined type`)console.log(getType('a'))// -> stringconsole.log(getType(1))// -> numberconsole.log(getType(undefined))// -> nullishconsole.log(getType(null))// -> nullish
实例判断
import { match, instanceOf } from 'babel-plugin-proposal-pattern-matching/match'const getType = val => match(val)( (v=instanceOf(RegExp))=>'RegExp', (v=instanceOf(Array))=>'Array', (v=instanceOf(Object))=>'Object',)console.log(getType(/111/))// -> RegExpconsole.log(getType([1,2,3]))// -> Arrayconsole.log(getType({a:1}))// -> Object
解构,这里反对有限嵌套
import { match } from 'babel-plugin-proposal-pattern-matching/match'const sum = x => match(x)( ([x, ...xs]) => x + sum(xs), ([]) => 0)console.log(sum([1, 2, 3]))// -> 6for (let i = 1; i <= 15; i++) { console.log( match({a: i % 3, b: i % 5})( ({a = 0, b = 0}) => 'FizzBuzz', ({a = 0, b}) => 'Fizz', ({a, b = 0}) => 'Buzz', _ => i ) )}// ->// 1// 2// Fizz// 4// Buzz// Fizz// 7// 8// Fizz// Buzz// 11// Fizz// 13// 14// FizzBuzz
非运算
import { match, not, or, T } from 'babel-plugin-proposal-pattern-matching/match'const toNumber = n => match(n)( (v = not(T.boolean)) => v, (v = true) => 1, (v = false) => 0)console.log( [true, false, 0, 1, 2, 3].map(toNumber))// -> [ 1, 0, 0, 1, 2, 3 ]
或运算
import { match, or } from 'babel-plugin-proposal-pattern-matching/match'const fib = n => match(n)( (v = or(1, 2)) => 1, _ => fib(_ - 1) + fib(_ - 2))console.log(fib(10))// -> 55
与运算
import { match, and, not } from 'babel-plugin-proposal-pattern-matching/match'const fib = n => match(n)( (_ = and(not(1), not(2))) => fib(_ - 1) + fib(_ - 2), _ => 1)console.log(fib(10))// -> 55