web-dev-qa-db-ja.com

ES6 / 2015のヌルセーフプロパティアクセス(および条件付き割り当て)

ES6(ES2015/JavaScript.next/Harmony)には、?. in CoffeeScriptなどのnull- safeプロパティアクセス(null伝播/存在)演算子がありますか?または、ES7で計画されていますか?

var aThing = getSomething()
...
aThing = possiblyNull?.thing

これは大体次のようになります。

if (possiblyNull != null) aThing = possiblyNull.thing

理想的には、undefinedaThingである場合、ソリューションはpossiblyNullに(nullでさえ)割り当てるべきではありません。

121
ᆼᆺᆼ

現在それを実現する機能は、現在ステージ1です:オプションのチェーン。

https://github.com/tc39/proposal-optional-chaining

今日使用したい場合は、それを実現するBabelプラグインがあります。

https://github.com/davidyaha/ecmascript-optionals-proposal

Update(2017-08-01):公式プラグインを使用する場合は、新しいトランスフォームでBabel 7のアルファビルドを試すことができます。 マイレージは異なる場合があります

https://www.npmjs.com/package/babel-plugin-transform-optional-chaining

79
basicdays

それは?ほど素敵ではありません。演算子ですが、同様の結果を得るには、次のようにします。

user && user.address && user.address.postcode

nullundefinedは両方ともfalsy値( このリファレンスを参照 )であるため、&&演算子の後のプロパティは、先行してnullまたは未定義ではありません。

または、次のような関数を作成することもできます。

function _try(func, fallbackValue) {
    try {
        var value = func();
        return (value === null || value === undefined) ? fallbackValue : value;
    } catch (e) {
        return fallbackValue;
    }
}

使用法:

_try(() => user.address.postcode) // return postcode or undefined 

または、代替値で:

_try(() => user.address.postcode, "none") // return postcode or a custom string
51
tocqueville

いいえ。JavaScriptで lodash#get などを使用できます。

31
Girafa

安全な資産アクセスのためのバニラ代替

(((a.b || {}).c || {}).d || {}).e

最も簡潔な条件付き割り当てはおそらくこれでしょう

try { b = a.b.c.d.e } catch(e) {}
12
yagger

いいえ、ES6にはヌル伝播演算子はありません。 既知のパターン のいずれかを使用する必要があります。

ただし、破壊を使用できる場合があります。

({thing: aThing} = possiblyNull);

ES7にそのような演算子を追加するための多くの議論(例えば this )がありますが、実際には何も始まりませんでした。

6
Bergi

リストを見てみると、 here 、現在、Ecmascriptに安全なトラバーサルを追加する提案はありません。したがって、これを行うための素晴らしい方法がないだけでなく、近い将来に追加されることはありません。

3
Antimony

これはJavaScriptの質問であることは知っていますが、Rubyは要求されたすべての方法でこれを処理していると思うので、関連する参照ポイントだと思います。

.&try、および&&には長所と潜在的な落とし穴があります。ここでこれらのオプションの素晴らしい概要: http://mitrev.net/Ruby/2015/11/13/the-operator-in-Ruby/

TLDR; Rubyistsの結論は、Digのほうが見やすく、valueまたはnullが割り当てられるという強力な保証の両方であるということです。

TypeScriptの簡単な実装を次に示します。

export function Dig(target: any, ...keys: Array<string>): any {
  let digged = target
  for (const key of keys) {
    if (typeof digged === 'undefined') {
      return undefined // can also return null or a default value
    }
    if (typeof key === 'function') {
      digged = key(digged)
    } else {
      digged = digged[key]
    }
  }
  return digged
}

これは、ネストの深さに使用でき、関数を処理します。

a = Dig(b, 'c', 'd', 'e');
foo = () => ({});
bar = Dig(a, foo, 'b', 'c')

前の回答で示したように、tryアプローチは、JSで読むのと同じくらいいいです。また、この実装の欠点の1つであるループを必要としません。

0
theUtherSide

安全なディープgetメソッドは、underscore.jsに自然に適合しているように見えますが、問題は文字列プログラミングを回避することです。文字列プログラミングを回避するために@Felipeの回答を変更します(または少なくともEdgeケースを呼び出し元にプッシュバックします):

function safeGet(obj, props) {
   return (props.length==1) ? obj[keys[0]] :safeGet(obj[props[0]], props.slice(1))
}

例:

var test = { 
  a: { 
    b: 'b property value',
    c: { }
  } 
}
safeGet(test, ['a', 'b']) 
safeGet(test, "a.b".split('.'))  
0
prototype