Javascript ES6/2015 中的空安全属性访问(和条件赋值)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32139078/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 07:39:28  来源:igfitidea点击:

Null-safe property access (and conditional assignment) in ES6/2015

javascriptcoffeescriptecmascript-6babeljs

提问by ???

Is there a null-safe property access (null propagation / existence) operator in ES6 (ES2015/JavaScript.next/Harmony) like ?.in CoffeeScriptfor example? Or is it planned for ES7?

例如,null在 ES6 (ES2015/JavaScript.next/Harmony)?.中是否有-safe 属性访问(空传播/存在)运算符,例如CoffeeScript?还是计划用于 ES7?

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

This will be roughly like:

这将大致如下:

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

Ideally the solution should not assign (even undefined) to aThingif possiblyNullis null

理想情况下,解决方案不应分配(甚至undefined)给aThingifpossiblyNullnull

采纳答案by basicdays

Update(2020-01-31): Seems people are still finding this, here's the current story:

更新(2020-01-31):似乎人们还在发现这个,这是当前的故事:

Update(2017-08-01): If you want to use an official plugin, you can try the alpha build of Babel 7 with the new transform. Your mileage may vary

更新(2017-08-01):如果你想使用官方插件,你可以尝试使用新转换的 Babel 7 alpha 版本。你的旅费可能会改变

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

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

Original:

原文

A feature that accomplishes that is currently in stage 1: Optional Chaining.

目前处于第 1 阶段的功能:可选链。

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

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

If you want to use it today, there is a Babel plugin that accomplishes that.

如果你今天想使用它,有一个 Babel 插件可以实现这一点。

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

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

回答by tocqueville

It's not as nice as the ?. operator, but to achieve a similar result you could do:

它不如?。运算符,但要获得类似的结果,您可以执行以下操作:

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

Since nulland undefinedare both falsyvalues (see this reference), the property after the &&operator is only accessed if the precedent it not null or undefined.

由于nullundefined都是值(请参阅此参考),因此&&仅当先例不为空或未定义时才访问运算符后面的属性。

Alternatively, you could write a function like this:

或者,您可以编写这样的函数:

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

Usage:

用法:

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

Or, with a fallback value:

或者,使用回退值:

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

回答by Girafa

No. You may use lodash#getor something like that for this in JavaScript.

不,你可以在 JavaScript 中使用lodash#get或类似的东西。

回答by yagger

Vanilla alternative for safe property access

安全访问财产的香草替代品

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

The most concise conditional assignment would probably be this

最简洁的条件赋值可能是这个

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

回答by Bergi

No, there is no null propagation operator in ES6. You will have to go with one of the known patterns.

不,ES6 中没有空传播运算符。您将不得不使用一种已知的模式

You may be able to use destructuring, though:

不过,您可以使用解构:

({thing: aThing} = possiblyNull);
({thing: aThing} = possiblyNull);

There are many discussions (e.g. this) to add such an operator in ES7, but none really took off.

有很多讨论(例如this)在 ES7 中添加这样的操作符,但没有一个真正起飞。

回答by Antimony

Going by the list here, there is currently no proposal to add safe traversal to Ecmascript. So not only is there no nice way to do this, but it is not going to be added in the forseeable future.

这里的列表来看,目前还没有建议将安全遍历添加到 Ecmascript。因此,不仅没有好的方法可以做到这一点,而且在可预见的未来也不会添加它。

回答by Gary Fu

// Typescript
static nullsafe<T, R>(instance: T, func: (T) => R): R {
    return func(instance)
}

// Javascript
function nullsafe(instance, func) {
    return func(instance);
};

// use like this
const instance = getSomething();
let thing = nullsafe(instance, t => t.thing0.thing1.thingx);

回答by prototype

A safe deep get method seems like a natural fit for underscore.js but there the issue is avoiding string programming. Modifying @Felipe's answer to avoid string programming (or at least pushes edge cases back to the caller):

安全的 deep get 方法似乎很适合 underscore.js,但问题在于避免字符串编程。修改@Felipe 的答案以避免字符串编程(或至少将边缘情况推回调用者):

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

Example:

例子:

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

回答by theUtherSide

I know this is a JavaScript question, but I think Ruby handles this in all of the requested ways, so I think it's a relevant point of reference.

我知道这是一个 JavaScript 问题,但我认为 Ruby 以所有要求的方式处理这个问题,所以我认为这是一个相关的参考点。

.&, try, and && have their strengths and potential pitfalls. A great run down of those options here: http://mitrev.net/ruby/2015/11/13/the-operator-in-ruby/

.&, try, 和 && 有它们的优点和潜在的缺陷。这里有很多这些选项:http: //mitrev.net/ruby/2015/11/13/the-operator-in-ruby/

TLDR; The Rubyists conclusion is that digis both easier on the eyes and a stronger guarantee that a valueor nullwill be assigned.

TLDR;Rubyists 的结论是,dig这既容易看又更能保证null将被分配。

Here's a simple imeplementation in TypeScript:

这是 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
}

This can be used for any depth of nesting and handles functions.

这可用于任何深度的嵌套和处理函数。

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

The tryapproach is equally nice to read in JS, as shown in previous answers. It also does not require looping, which is one drawback of this implementation.

try先前的答案所示,该方法同样适合在 JS 中阅读。它也不需要循环,这是此实现的一个缺点。

回答by Felipe

I thought this question needed a bit of a refresh for 2018. This can be done nicely without any libraries using Object.defineProperty()and can be used as follows:

我认为这个问题需要在 2018 年稍微更新一下。 这可以在不使用任何库的情况下很好地完成,Object.defineProperty()并且可以如下使用:

myVariable.safeGet('propA.propB.propC');

I consider this safe (and js-ethical) because of the writeableand enumerabledefinitions now available for the definePropertymethod of Object, as documented in MDN

我认为这是安全的(和 js-ethical),因为writeableenumerable定义现在可用于 的defineProperty方法Object,如MDN 中所述

function definition below:

函数定义如下:

Object.defineProperty(Object.prototype, 'safeGet', { 
    enumerable: false,
    writable: false,
    value: function(p) {
        return p.split('.').reduce((acc, k) => {
            if (acc && k in acc) return acc[k];
            return undefined;
        }, this);
    }
});

I've put together a jsBinwith console output to demonstrate this. Note that in the jsBin version I've also added a custom exception for empty values. This is optional, and so I've left it out of the minimal definition above.

我已经将一个带有控制台输出的jsBin放在一起来演示这一点。请注意,在 jsBin 版本中,我还为空值添加了自定义异常。这是可选的,所以我把它排除在上面的最小定义之外。

Improvements are welcomed

欢迎改进