javascript 中是否有空合并(Elvis)运算符或安全导航运算符?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6613952/
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
Is there a null-coalescing (Elvis) operator or safe navigation operator in javascript?
提问by tiagomac
I'll explain by example:
我将举例说明:
Elvis Operator (?: )
猫王运算符 (?:)
The "Elvis operator" is a shortening of Java's ternary operator. One instance of where this is handy is for returning a 'sensible default' value if an expression resolves to false or null. A simple example might look like this:
“Elvis 运算符”是 Java 的三元运算符的缩写。这很方便的一个例子是,如果表达式解析为 false 或 null,则返回一个“合理的默认”值。一个简单的例子可能如下所示:
def gender = user.male ? "male" : "female" //traditional ternary operator usage
def displayName = user.name ?: "Anonymous" //more compact Elvis operator
Safe Navigation Operator (?.)
The Safe Navigation operator is used to avoid a NullPointerException. Typically when you have a reference to an object you might need to verify that it is not null before accessing methods or properties of the object. To avoid this, the safe navigation operator will simply return null instead of throwing an exception, like so:
安全导航操作员 (?.)
安全导航运算符用于避免 NullPointerException。通常,当您有一个对象的引用时,您可能需要在访问该对象的方法或属性之前验证它是否为空。为了避免这种情况,安全导航运算符将简单地返回 null 而不是抛出异常,如下所示:
def user = User.find( "admin" ) //this might be null if 'admin' does not exist
def streetName = user?.address?.street //streetName will be null if user or user.address is null - no NPE thrown
采纳答案by Lime
You can use the logical 'OR' operator in place of the Elvis operator:
您可以使用逻辑“OR”运算符代替 Elvis 运算符:
For example displayname = user.name || "Anonymous"
.
例如displayname = user.name || "Anonymous"
。
But Javascript currently doesn't have the other functionality. I'd recommend looking at CoffeeScriptif you want an alternative syntax. It has some shorthand that is similar to what you are looking for.
但是 Javascript 目前没有其他功能。如果您想要替代语法,我建议您查看CoffeeScript。它有一些与您正在寻找的类似的速记。
For example The Existential Operator
例如存在运算符
zip = lottery.drawWinner?().address?.zipcode
Function shortcuts
功能快捷键
()-> // equivalent to function(){}
Sexy function calling
性感的函数调用
func 'arg1','arg2' // equivalent to func('arg1','arg2')
There is also multiline comments and classes. Obviously you have to compile this to javascript or insert into the page as <script type='text/coffeescript>'
but it adds a lot of functionality :) . Using <script type='text/coffeescript'>
is really only intended for development and not production.
还有多行注释和类。显然,您必须将其编译为 javascript 或插入到页面中,<script type='text/coffeescript>'
但它增加了很多功能 :) 。使用<script type='text/coffeescript'>
实际上仅用于开发而不是生产。
回答by samjudson
I think the following is equivalent to the safe navigation operator, although a bit longer:
我认为以下相当于安全导航操作符,虽然有点长:
var streetName = user && user.address && user.address.street;
streetName
will then be either the value of user.address.street
or undefined
.
streetName
然后将是任一值user.address.street
或undefined
。
If you want it to default to something else you can combine with the above shortcut or to give:
如果您希望它默认为其他内容,您可以结合上述快捷方式或给出:
var streetName = (user && user.address && user.address.street) || "Unknown Street";
回答by Frédéric Hamidi
Javascript's logical OR operatoris short-circuitingand can replace your "Elvis" operator:
Javascript 的逻辑 OR 运算符是短路的,可以替换您的“Elvis”运算符:
var displayName = user.name || "Anonymous";
However, to my knowledge there's no equivalent to your ?.
operator.
但是,据我所知,没有相当于您的?.
运营商。
回答by James_pic
I've occasionally found the following idiom useful:
我偶尔发现以下习语很有用:
a?.b?.c
can be rewritten as:
可以改写为:
((a||{}).b||{}).c
This takes advantage of the fact that getting unknown attributes on an object returns undefined, rather than throwing an exception as it does on null
or undefined
, so we replace null and undefined with an empty object before navigating.
这利用了在对象上获取未知属性返回 undefined 的事实,而不是像null
or那样抛出异常undefined
,因此我们在导航之前将 null 和 undefined 替换为空对象。
回答by tony_k
回答by Hyman Tuck
Not yet. Maybe soon. There is currently a draft spec:
还没有。也许很快。目前有一个草案规范:
https://github.com/tc39/proposal-optional-chaining
https://github.com/tc39/proposal-optional-chaining
https://tc39.github.io/proposal-optional-chaining/
https://tc39.github.io/proposal-optional-chaining/
For now, though, I like to use lodash get(object, path [,defaultValue])
or dlv delve(obj, keypath)
现在,虽然,我喜欢用lodashget(object, path [,defaultValue])
或DLVdelve(obj, keypath)
回答by jabacchetta
2019 Update
2019年更新
JavaScript now has equivalents for both the Elvis Operator and the Safe Navigation Operator.
JavaScript 现在具有 Elvis Operator 和 Safe Navigation Operator 的等效项。
Safe Property Access
安全的财产访问
The optional chaining operator(?.
) is currently a stage 4ECMAScript proposal. You can use it today with Babel.
在可选的链接运营商(?.
)是目前阶段4ECMAScript的建议。你今天可以在 Babel 中使用它。
// `undefined` if either `a` or `b` are `null`/`undefined`. `a.b.c` otherwise.
const myVariable = a?.b?.c;
The logical AND operator(&&
) is the "old", more-verbose way to handle this scenario.
该逻辑AND运算符(&&
)是“老”,更详细的处理这种情况的方式。
const myVariable = a && a.b && a.c;
Providing a Default
提供默认值
The nullish coalescing operator(??
) is currently a stage 3ECMAScript proposal. You can use it today with Babel. It allows you to set a default value if the left-hand side of the operator is a nullary value (null
/undefined
).
该nullish合并运算符(??
)是目前第3阶段的ECMAScript建议。你今天可以在 Babel 中使用它。如果运算符的左侧是空值 ( null
/ undefined
),它允许您设置默认值。
const myVariable = a?.b?.c ?? 'Some other value';
// Evaluates to 'Some other value'
const myVariable2 = null ?? 'Some other value';
// Evaluates to ''
const myVariable3 = '' ?? 'Some other value';
The logical OR operator(||
) is an alternative solution with slightly different behavior. It allows you to set a default value if the left-hand side of the operator is falsy. Note that the result of myVariable3
below differs from myVariable3
above.
的逻辑OR运算符(||
)是一种替代解决方案略有不同的行为。如果运算符的左侧为falsy ,它允许您设置默认值。请注意,myVariable3
下面的结果与myVariable3
上面的不同。
const myVariable = a?.b?.c || 'Some other value';
// Evaluates to 'Some other value'
const myVariable2 = null || 'Some other value';
// Evaluates to 'Some other value'
const myVariable3 = '' || 'Some other value';
回答by hobbs
For the former, you can use ||
. The Javascript "logical or" operator, rather than simply returning canned true and false values, follows the rule of returning its left argument if it is true, and otherwise evaluating and returning its right argument. When you're only interested in the truth value it works out the same, but it also means that foo || bar || baz
returns the leftmost one of foo, bar, or baz that contains a true value.
对于前者,您可以使用||
. Javascript“逻辑或”运算符,而不是简单地返回固定的真值和假值,遵循以下规则:如果为真则返回其左参数,否则评估并返回其右参数。当您只对真值感兴趣时,结果相同,但这也意味着foo || bar || baz
返回包含真值的 foo、bar 或 baz 中最左边的一个。
You won't find one that can distinguish false from null, though, and 0 and empty string are false values, so avoid using the value || default
construct where value
can legitimately be 0 or ""
.
但是,您不会找到可以区分 false 和 null 的值,并且 0 和空字符串是 false 值,因此请避免使用value || default
构造 wherevalue
可以合法地为 0 或""
。
回答by gazdagergo
Yes, there is!
就在这里!
Optional chainingis in stage 4 and this enables you to use the user?.address?.street
formula.
可选链接处于第 4 阶段,这使您能够使用user?.address?.street
公式。
If you can't wait the release, install @babel/plugin-proposal-optional-chaining
and you can use it.
Here are my settings which works for me, or just read Nimmo's article.
如果您等不及发布,请安装@babel/plugin-proposal-optional-chaining
并使用它。以下是适用于我的设置,或者只是阅读Nimmo 的文章。
// package.json
{
"name": "optional-chaining-test",
"version": "1.0.0",
"main": "index.js",
"devDependencies": {
"@babel/plugin-proposal-optional-chaining": "7.2.0",
"@babel/core": "7.2.0",
"@babel/preset-env": "^7.5.5"
}
...
}
// .babelrc
{
"presets": [
[
"@babel/preset-env",
{
"debug": true
}
]
],
"plugins": [
"@babel/plugin-proposal-optional-chaining"
]
}
// index.js
console.log(user?.address?.street); // it works
回答by cdmckay
Here's a simple elvis operator equivalent:
这是一个简单的 elvis 运算符等效项:
function elvis(object, path) {
return path ? path.split('.').reduce(function (nestedObject, key) {
return nestedObject && nestedObject[key];
}, object) : object;
}
> var o = { a: { b: 2 }, c: 3 };
> elvis(o)
{ a: { b: 2 }, c: 3 }
> elvis(o, 'a');
{ b: 2 }
> elvis(o, 'a.b');
2
> elvis(o, 'x');
undefined