JavaScript 未来的功能

大家都觉得 ES6 带来这么多新功能,让人很兴奋。
同样让人兴奋的是,在 ES6 之后,JS 将保持一年一次的迭代频率,这使得 JS 能紧跟时代,保持充沛的生命力。

JS 的迭代方式是“提案制”,即谁都可向 Ecma TC39 提出迭代方案,方案过了初审后,便要走 stage0 ~ stage4 的流程,stage4 表示提案确定被采纳,但提案走到 stage2 基本就确定会被采纳。如开发中常用的 stage3 的 import() ,stage2 的 Decorator 等等。

下面介绍几个虽处于 stage1,但很棒的提案。
PS: 其实这些功能,原生JS 和 Lodash 都能实现...
那么,既然都能实现了,为啥新版本还有加入这些功能?
嗯,这是个好问题...

先说实现了 函数式编程 中 柯里化 和 compose 的两个功能:

1. partial-application - 柯里化,亦可叫 偏函数

例如,我们分别用 原生JS,Lodash 和 partial-application 实现将 add(a, b) 柯里化为 addTen(n):

function add(a, b) {
  return a + b;
}

// 原生JS:
const addTen = add.bind(null, 10);

// Ladash:
const addTen = _.curry(add)(10);

// partial-application:
const addTen = add(10, ?);
// 或者
const addTen = add(?, 10);

上面三者,都实现了柯里化的效果,但细微之处还是有区别:

  • 原生JS通过 bind() ,但这与 bind 的主要用途不符,降低了代码的可读性。
  • Lodash 用 _.curry() 有不错的可读性,但也需要对闭包有一定的了解才能熟练地使用。
  • partial-application 极大简洁了实现的代码,并且并不止于柯里化中必须将参数从左至右一个个“reduce”的形式,甚至开发者都不需懂得柯里化的概念,便能很好地使用该功能。

2. pipeline-operator - compose,亦 node 中的 Stream

开发中,我们经常会遇到,某一数据,要将其依次经几个函数处理。
如我们要将 "hello" 经下面三个函数处理后,输出 "Hello, hello!":

function doubleSay (str) {
  return str + ", " + str;
}
function capitalize (str) {
  return str[0].toUpperCase() + str.substring(1);
}
function exclaim (str) {
  return str + '!';
}

我们分别用 原生JS,Lodash 和 pipeline-operator 实现看看:

// 原生JS:
exclaim(capitalize(doubleSay("hello")));  //"Hello, hello!"

// Lodash:
_.flow([
  doubleSay
  capitalize
  exclaim
])("hello");    //"Hello, hello!"

// pipeline-operator:
const result = "hello"
  |> doubleSay
  |> capitalize
  |> exclaim;
console.log(result);  // "Hello, hello!"

如上,三者都能实现 compose 的效果,而三者的表现形式还是如上面实现 柯里化 很接近:

  • 原生JS 都写法,可读性差。
  • Lodash 用 _.flow() 有不错的可读性,也还是运用了闭包。
  • pipeline-operator 最大程度简洁了代码。

3. optional-chaining - 链式引用

当我们深层引用一对象都属性时,往往每层都引用都需做 undefined 判断,以防止 undefined.xxx 报错。 特别是在使用 ajax 传来的 json 时,更是要小心翼翼,因为 ajax 的数据会有各种不确定性。
所以,在 原生JS 中,我们经常会这样写:

var house = user.address && user.address.street && user.address.street.house;

使用了 lodash 的 _.get() 我们可以这样写:

var house = _.get(user, 'address.street.house')

而有了 optional-chaining 我们可以这样写:

var house = user.address?.street?.house;


以上,就是 stage1 中很酷的几个提案。
从中可以看出,除了扩展 JS 的能力,JS 还在朝使用更简单、可读性更好、增强函数式编程的能力、引入更多的设计模式等方向发展。

回到最开始的问题,既然用 hack 或 Lodash 能实现的功能,为啥 JS 还要加入这些功能?
我觉得让 JS 更简单易用的目的不言自明。
更重要的是 hack 技巧或 Lodash 很多开发人员并不会掌握的很好,而这些功能又是这么的有价值。
将这些功能集成进 JS 后,能更好的推广这些有价值的功能,进而提升 JS 世界的整体能力。
从宏观角度看,这种价值是巨大的。

推荐阅读更多精彩内容