模式匹配(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