ES6解构预处理

Cha*_*lie 5 javascript destructuring ecmascript-6

问题

函数参数解构是ES6中的一个惊人特性.假设我们希望一个functionnamed f接受一个Objecta密钥的

function f({ a }) {
    return a;
}
Run Code Online (Sandbox Code Playgroud)

对于未提供参数的情况,我们有默认值以避免 Type Error

function f({ a } = {}) {
    return a;
}
Run Code Online (Sandbox Code Playgroud)

这将有助于以下情况

const a = f(); // undefined
Run Code Online (Sandbox Code Playgroud)

虽然,它会失败

const a = f(null); // TypeError: Cannot match against 'undefined' or 'null'.
Run Code Online (Sandbox Code Playgroud)

您可以在这里看到Babel如何将功能转换为ES5 .

可能的解决方案

通过参数验证和预处理可以避免这种情况.在Python我可以使用装饰器,但在JS中我们没有它们标准化,所以使用它们不是一个好主意.但是,假设我们有一个装饰器checkInputObject,它使用给定的项目列表(或嵌套解构的情况下的树)进行必要的检查并提供默认值.我们可以在没有@表示法的情况下以下列方式使用它

const f = checkInputObject(['a'])(({ a }) => a);
Run Code Online (Sandbox Code Playgroud)

它可能看起来像带@符号

@checkInputObject(['a'])
function f({ a }) {
    return a;
}
Run Code Online (Sandbox Code Playgroud)

此外,我可以在函数本身中进行所有需要的操作,然后才使用解构,但在这种情况下,我失去了函数参数解构的所有优点(我根本不会使用它)

function f(param) {
    if (!param) {
        return;
    }
    const { a } = param;
    return a;
}
Run Code Online (Sandbox Code Playgroud)

我甚checkInputObject至可以实现一些常见的功能,以便在函数内部使用它

const fChecker = checkInputObject(['a']);
function f(param) {
    const { a } = fChecker(param);
    return a;
}
Run Code Online (Sandbox Code Playgroud)

但是,使用附加代码对我来说并不优雅.我想没有现有的实体被分解为undefined.假设我们有

function f({a: [, c]) {
    return c;
}
Run Code Online (Sandbox Code Playgroud)

得到undefined的情况会很好f().

你知道任何优雅和方便的方法使[嵌套]解构抵抗不存在的嵌套键吗?

我关注的是:看起来这个功能对于在公共方法中使用是不安全的,我需要在使用之前自己进行验证.这就是为什么它在私人方法中使用之前似乎毫无用处.

Est*_*ask 2

在 ES6 中处理此问题的正确方法是尊重语言和形状 API 处理参数的方式,以更好地适应它,而不是相反。

解构参数背后的语义fn(undefined)是参数将被替换为默认值,在 的情况下意味着fn(null)空参数不会被默认值替换。

如果数据来自外部并且应该进行条件/预处理/验证,则应该显式处理,而不是通过解构:

function fn({ foo, bar}) { ... }

fn(processData(data));
Run Code Online (Sandbox Code Playgroud)

或者

function fn(data) {
  const { foo, bar } = processData(data);
  ...
}

fn(data);
Run Code Online (Sandbox Code Playgroud)

processData应该调用的地方完全由开发人员决定。

@由于提议的 ECMAScript 装饰器只是具有特定签名的辅助函数,因此根据项目的不同,相同的辅助函数可以用于语法和常用函数调用。

function processDataDecorator(target, key) {
  const origFn = target[key];
  return target[key] = (...args) => origFn.apply(target, processData(...args));
}

class Foo {
  constructor() {
    this.method = processDataDecorator(this, 'method');
  }

  method(data) {...}
}

class Bar {
  @processDataDecorator
  method(data) {...}
}
Run Code Online (Sandbox Code Playgroud)

自 ES5 以来,该语言提供的默认属性值的方式是Object.assign. dataisundefined或其他原语并不重要null,结果将始终是一个对象:

function processData(data) {
  return Object.assign({ foo: ..., bar: ...}, data);
}
Run Code Online (Sandbox Code Playgroud)