簡體   English   中英

ES6解構預處理

[英]ES6 destructuring preprocessing

問題

函數參數解構是ES6中的一個驚人特性。 假設我們希望有一個functionf接受的Object ,其具有a

function f({ a }) {
    return a;
}

對於未向函數提供參數以避免Type Error的情況,我們有默認值

function f({ a } = {}) {
    return a;
}

這將有助於以下情況

const a = f(); // undefined

雖然,它會失敗

const a = f(null); // TypeError: Cannot match against 'undefined' or 'null'.

您可以在這里看到Babel如何將功能轉換為ES5。

可能的解決方案

通過參數驗證和預處理可以避免這種情況。 Python我可以使用裝飾器,但在JS中我們沒有標准化,所以使用它們並不是一個好主意。 但是,假設我們有一個裝飾器checkInputObject ,它使用給定的項目列表(或嵌套解構的情況下的樹)進行必要的檢查並提供默認值。 我們可以在沒有@ notation的情況下以下列方式使用它

const f = checkInputObject(['a'])(({ a }) => a);

@ notation可能看起來像這樣

@checkInputObject(['a'])
function f({ a }) {
    return a;
}

此外,我可以在函數本身中進行所有需要的操作,然后才使用解構,但在這種情況下,我失去了函數參數解構的所有優點(我根本不會使用它)

function f(param) {
    if (!param) {
        return;
    }
    const { a } = param;
    return a;
}

我甚至可以實現一些像checkInputObject這樣的常用函數,以便在函數內部使用它

const fChecker = checkInputObject(['a']);
function f(param) {
    const { a } = fChecker(param);
    return a;
}

但是,使用附加代碼對我來說並不優雅。 我希望沒有現有的實體被分解為undefined 假設我們有

function f({a: [, c]) {
    return c;
}

f()的情況下得到undefined會很好。

你知道任何優雅和方便的方法使[嵌套]解構抵抗不存在的嵌套鍵嗎?

我關注的是:看起來這個功能對於在公共方法中使用是不安全的,我需要在使用之前自己進行驗證。 這就是為什么它在私人方法中使用之前似乎毫無用處。

您可以使用try...catch並在通用裝飾器函數中使用它:

 function safe(f) { return function (...args) { try { return f(...args); } catch (e) {}; // return undefined }; } function f({ a } = {}) { return a; } f = safe(f); console.log(f(null)); // -> undefined console.log(f( { a:3 } )); // -> 3 

我相信我可以通過向您展示不同的方式來幫助您解決此問題。

您面臨的問題不在於解構,因為您將在任何函數中面對它,而您正在發送它所期望的不同類型。

解決這個問題,例如 在解構時,您可以使用類型檢查解決方案,例如Flow ,它會靜態檢查類型,因此每當您向函數發送錯誤的內容時,它都會在構建時失敗。

javascript的本質是它是一種動態類型語言,因此您可能希望該函數能夠處理發送給它的任何參數,在這種情況下,您可以使用動態類型檢查,解決方案很多。

函數參數更多地是你對如何使用函數的“協議”,而不是訪問它的參數(畢竟你可以只使用arguments來訪問它們),因此通過發送不同的東西你違反了這個協議,這不是不管怎樣,一個好的做法,最好有1個功能做1件事,並盡可能少地接受復雜的參數。

在ES6中處理這個問題的正確方法是尊重語言和形狀API處理params的方式以更好地適應它,而不是相反的方式。

fn(undefined)析構參數背后的語義是參數將被替換為默認值,在fn(null)的情況下,nully參數不會被默認值替換。

如果數據來自外部並且應該進行條件/預處理/驗證,則應該明確處理,而不是通過解構:

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

fn(processData(data));

要么

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

fn(data);

應該調用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) {...}
}

自ES5以來語言為默認屬性值提供的方式是Object.assign 如果data undefinednull或其他原語並不重要,結果將始終是一個對象:

function processData(data) {
  return Object.assign({ foo: ..., bar: ...}, data);
}

難道你不是自己回答你問的問題嗎?

我認為默認參數是更優雅的方式。

function f({a: [,c]}={a:[undefined,undefined]}) {
    return c;
}

f();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM