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

IT技术 javascript coffeescript ecmascript-6 babeljs
2021-01-18 15:55:53

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

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

这将大致如下:

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

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

6个回答

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

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

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

原文

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

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

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

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

实际上不幸的是,我认为你是对的。Street 我想会被分配undefined至少它不会试图访问未定义的属性。
2021-03-10 15:55:53
关于 左侧的条件赋值,=目前官方规范似乎不支持。github.com/tc39/proposal-optional-chaining#not-supported
2021-03-17 15:55:53
截至 2020 年 5 月,看起来当前的浏览器和 Typescript 已经实现了这一点!
2021-03-28 15:55:53
我是否正确理解这不包括条件分配?street = user.address?.street无论如何都会设置street
2021-04-04 15:55:53
看起来您也可以使用左侧的运算符,如果将任何内容评估为未定义,则不会评估右手。babel 插件可能会有所不同,我自己还没有测试过。
2021-04-06 15:55:53

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

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

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

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

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
可能我应该澄清这个问题,我所追求的主要是条件分配
2021-03-12 15:55:53
foo && foo.bar && foo.bar.quux ... 在大型代码库中,这很丑陋,并且增加了很多您最好避免的复杂性。
2021-03-14 15:55:53
这是我在互联网上找到的最干净的解决方案。我在typescript中使用它:_get<T>(func: () => T, fallbackValue?: T) :T
2021-03-23 15:55:53
只是一个推论;要安全地找到逆,您可以使用 !(user && user.address && user.address.postcode) :)
2021-03-24 15:55:53
如果user.address.postcode未定义,_try(() => user.address.postcode, "")将返回undefined而不是""所以代码_try(() => user.address.postcode, "").length会引发异常。
2021-04-04 15:55:53

2020 解决方案,?.以及??

您现在可以直接使用?.(Optional Chaining) 内联来安全地测试是否存在。所有现代浏览器都支持它。

?? (Nullish Coalescing) 可用于在未定义或为空的情况下设置默认值。

aThing = possiblyNull ?? aThing
aThing = a?.b?.c ?? possiblyNullFallback ?? aThing

如果属性存在,则?.继续下一个检查,或返回有效值。任何故障都会立即短路并返回undefined

const example = {a: ["first", {b:3}, false]}

example?.a  // ["first", {b:3}, false]
example?.b  // undefined

example?.a?.[0]     // "first"
example?.a?.[1]?.a  // undefined
example?.a?.[1]?.b  // 3

domElement?.parentElement?.children?.[3]?.nextElementSibling

null?.()                // undefined
validFunction?.()       // result
(() => {return 1})?.()  // 1

为确保默认定义值,您可以使用??. 如果您需要第一个真值,您可以使用||.

example?.c ?? "c"  // "c"
example?.c || "c"  // "c"

example?.a?.[2] ?? 2  // false
example?.a?.[2] || 2  // 2

如果不检查 case,则 left-side 属性必须存在。如果没有,它会抛出异常。

example?.First         // undefined
example?.First.Second  // Uncaught TypeError: Cannot read property 'Second' of undefined

?.浏览器支持- 92%,2021 年 11 月

??浏览器支持- 92%

Mozilla 文档

——

逻辑空赋值,2020+解决方案

目前正在向浏览器??=||=和 中添加新的运算符&&=它们并不能完全满足您的要求,但可能会导致相同的结果,具体取决于您的代码目标。

注意:这些在公共浏览器版本中还不常见,但 Babel 应该可以很好地转换。将随着可用性的变化而更新。

??=检查左侧是否未定义或为空,如果已定义则短路。如果不是,则左侧被分配右侧值。||=and&&=是相似的,但基于||and&&运算符。

基本示例

let a          // undefined
let b = null
let c = false

a ??= true  // true
b ??= true  // true
c ??= true  // false

对象/数组示例

let x = ["foo"]
let y = { foo: "fizz" }

x[0] ??= "bar"  // "foo"
x[1] ??= "bar"  // "bar"

y.foo ??= "buzz"  // "fizz"
y.bar ??= "buzz"  // "buzz"

x  // Array [ "foo", "bar" ]
y  // Object { foo: "fizz", bar: "buzz" }

浏览器支持2021 年 11 月 - 90%

Mozilla 文档

添加了一些带有?.和 的示例,以及??可能适用于您的情况的详细的即将推出的解决方案。当前最好的解决方案可能就是做aThing = possiblyNull?.thing ?? aThing
2021-03-10 15:55:53
这个问题也是关于条件分配的
2021-04-09 15:55:53

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

是否有建议将其添加到 ES7?
2021-03-19 15:55:53
@PeterVarga:很多。过多的讨论。这个功能的语法不是一件容易的事
2021-03-21 15:55:53
lodash.get 稍有不同,显然它不能进行条件赋值。
2021-03-21 15:55:53
没遇到过
2021-04-05 15:55:53

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

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

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

try { b = a.b.c.d.e } catch(e) {}
当然,您仍然需要检查您是否希望分配发生。如果您使用 '=' 运算符,将不可避免地分配某些内容,无论是数据、未定义还是空值。所以以上只是一个安全的属性访问。条件赋值运算符在任何语言中都存在吗?
2021-03-30 15:55:53
当然,例如CoffeeScript,它也有||=
2021-04-01 15:55:53
那么你将如何使用这种机制在问题中编写作业呢?如果possiblyNull未定义/,您是否仍然需要不分配的条件null
2021-04-09 15:55:53
+1 甚至我的第一个想法是(((a.b || {}).c || {}).d || {}).e但更精确的是((((a || {}).b || {}).c || {}).d || {}).e
2021-04-09 15:55:53