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
Null-safe property access (and conditional assignment) in ES6/2015
提问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 aThing
if possiblyNull
is null
理想情况下,解决方案不应分配(甚至undefined
)给aThing
ifpossiblyNull
是null
采纳答案by basicdays
Update(2020-01-31): Seems people are still finding this, here's the current story:
更新(2020-01-31):似乎人们还在发现这个,这是当前的故事:
- Optional Chaining specification (Stage 4): https://github.com/tc39/proposal-optional-chaining
- babel-preset-env: This is probably what you wanthttps://babeljs.io/docs/en/babel-preset-env
- Babel v7 Plugin: https://babeljs.io/docs/en/babel-plugin-proposal-optional-chaining
- 可选链规范(第 4 阶段):https: //github.com/tc39/proposal-optional-chaining
- babel-preset-env:这可能就是你想要的https://babeljs.io/docs/en/babel-preset-env
- Babel v7 插件:https: //babeljs.io/docs/en/babel-plugin-proposal-optional-chaining
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 插件可以实现这一点。
回答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 null
and undefined
are both falsyvalues (see this reference), the property after the &&
operator is only accessed if the precedent it not null or undefined.
由于null
和undefined
都是假值(请参阅此参考),因此&&
仅当先例不为空或未定义时才访问运算符后面的属性。
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
回答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 dig
is both easier on the eyes and a stronger guarantee that a valueor null
will 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 try
approach 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 writeable
and enumerable
definitions now available for the defineProperty
method of Object
, as documented in MDN
我认为这是安全的(和 js-ethical),因为writeable
和enumerable
定义现在可用于 的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
欢迎改进