平滑 JavaScript
封面图片由 David 在 Flickr 上发布,由我裁剪。
作为一名 JavaScript 开发者,你可能听说过 smoosh-gate。一些TC39成员(负责设计定义 JavaScript 语言行为的 ECMAScript 标准)提出了将重命名 flatten为smoosh和flatMap的想法smooshMap。这样做的原因是,如果不这样做,一些使用 MooTools 的网站可能会崩溃。这些方法目前还处于提案阶段,并非标准的一部分。
无论如何,我对 MooTools 或标准了解不多,但我想解释一下这些功能实际上起什么作用。
为什么
在编写 JavaScript 代码时,你可能经常会用到你最喜欢的函子、数组和 Promise。有时它们是嵌套的,但你并不在意。你需要一个数字数组,而不是一个数字数组的数组;或者你需要从服务器获取 JSON 结果,而不是一个包含 JSON 结果的 Promise。
什么
承诺已经带有一种then方法,可以展平嵌套的承诺。
// loadDataA returns a promise
const dataAPromise = loadDataA();
// dataAPromise resolves to a result with an id that is used to load the next data
// loadDataB returns a promise too
const dataBPromise = dataAPromise.then(result => loadDataB(result.id))
// dataBPromise resolves to the resulting data
// and not the the promise returned from the callback above.
// It's flattened out right away so you only care about the result
const upperCasePromise = dataBPromise.then(result => result.someText.toUpperCase())
// upperCasePromise resolves to the upper case text
// returned by the previous callback.
upperCasePromise.then(upperCaseText => console.log(upperCaseText));
所以这里没什么可做的。一些 Promise 库,比如Bluebird,自带了单独的map和flatMap方法,但你主要会用到它们then,所以不用太在意这里的扁平化。
解决数组中这个问题的方法是向数组添加flattenand方法。该方法会用嵌套元素的内容替换数组中的每个嵌套元素,并删除空元素。flatMapflatten
该函数可以借助手动编写reduce。
const flatten = a => a.reduce(
  (newArray, element) =>
    element instanceof Array
      ? [...newArray, ...element]
      : element !== undefined? [...newArray, element] : newArray,
  []
);
const a = [1, [2, 3, 4], , 5];
flatten(a); // -> [1, 2, 3, 4, 5]
我们通过将每个元素添加到其中来简化a为一个,如果这个数组是一个,我们将其中的每个元素添加到中。(对于任何一种情况,-operator 都会创建一个新数组,而不是添加到现有数组中,但我想你明白我的意思)。newArrayelementistanceof ArrayelementnewArray...
命令式版本可能如下所示:
function flatten(a) {
  let b = [];
  for (let element of a) {
    if (element instanceof Array) {
      for (let subElement of element) {
        b.push(subElement);
      }
    } else if (element !== undefined) {
      b.push(element);
    }
  }
  return b;
}
const a = [1, [2, 3, 4], , 5];
flatten(a); // -> [1, 2, 3, 4, 5]
此版本flatMap只是调用flatten由 a 发出的新数组map。
const flatMap = (f, a) => flatten(a.map(f));
const a = [1,0,7,-3];
flatMap(x => x != 0? 1/x : undefined, a);
// -> [1, 0.14285714285714285, -0.3333333333333333]
const c = [1,2,5];
flatMap(x => ''.padEnd(x, ".").split(""), c);
// -> [".", ".", ".", ".", ".", ".", ".", "."]
真正的实现可能像方法而不是函数一样工作:
// Instead of 
flatten(a.map(x => [1,x]));
// it would be
a.map(x => [1,x]).flatten();
// instead of
flatMap(x => [1,x], a);
// it would be
a.flatMap(x => [1,x]);
结论
扁平化是每个程序中多次执行的一个相当重要的操作,所以如果 JavaScript 附带一个内置版本,与其最终名称无关,那就太好了,哈哈。
文章来源:https://dev.to/kayis/smooshing-javascript--5dpc 后端开发教程 - Java、Spring Boot 实战 - msg200.com
            后端开发教程 - Java、Spring Boot 实战 - msg200.com