是否有一个null
-safe属性访问(空传播/存在)操作者在ES6(ES2015 / JavaScript.next /和谐)等?.
中的CoffeeScript例如?还是计划针对ES7?
var aThing = getSomething()
...
aThing = possiblyNull?.thing
大致如下所示:
if (possiblyNull != null) aThing = possiblyNull.thing
理想情况下,解决方案不应该分配(甚至undefined
)到aThing
如果possiblyNull
ISnull
更新(2020-01-31):似乎人们仍在寻找这个,这是当前故事:
- 可选的链接规范(第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
更新(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
它不如?好。运算符,但是要达到类似的结果,您可以执行以下操作:
user && user.address && user.address.postcode
由于null
和undefined
都是伪造的值(请参阅此参考资料),&&
只有在先例不是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
否。您可以在JavaScript中使用lodash#get或类似的方法。
香草替代品,可安全进入物业
(((a.b || {}).c || {}).d || {}).e
最简洁的条件分配可能是这样
try { b = a.b.c.d.e } catch(e) {}
不,ES6中没有空传播算子。您将不得不采用一种已知模式。
您也许可以使用解构:
({thing: aThing} = possiblyNull);
有很多讨论(例如this)在ES7中添加这样的运算符,但没有一个真正起步。
按照此处的列表进行操作,当前没有提议向Ecmascript添加安全遍历。因此,不仅没有很好的方法可以做到这一点,而且在可预见的将来也不会添加它。
2020解决方案,?.
以及??
现在,您可以直接使用?.
(可选链接)内联安全地测试存在性。所有现代的浏览器都支持它。
??
(空合并)可用于设置默认值(如果未定义或为null)。
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
如果不检查情况,则必须存在left-side属性。如果没有,它将抛出异常。
example?.First // undefined
example?.First.Second // Uncaught TypeError: Cannot read property 'Second' of undefined
?.
浏览器支持-2020年10月占82%
??
浏览器支持-82%
-
逻辑无效分配,2020 +解决方案
当前正在将新的运算符添加到浏览器中??=
,||=
和&&=
。它们不能完全满足您的要求,但根据您的代码目标,可能会导致相同的结果。
注意:这些在公共浏览器版本中尚不常见,但是Babel应该可以很好地进行移植。将随着可用性的变化而更新。
??=
检查左侧是否未定义或为null,如果已定义则短路。如果不是,则为左侧分配右侧值。||=
和&&=
相似,但基于||
和&&
运算符。
基本范例
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" }
浏览器支持2020年10月-70%
// 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);
安全的深度获取方法似乎很自然地适合underscore.js,但是问题是避免进行字符串编程。修改@Felipe的答案以避免字符串编程(或至少将边沿大小写推回调用方):
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('.'))
我知道这是一个JavaScript问题,但我认为Ruby以所有要求的方式处理此问题,因此我认为这是一个相关的参考点。
.&
,,try
和&&具有优势和潜在的陷阱。这些选项的摘要如下:http : //mitrev.net/ruby/2015/11/13/the-operator-in-ruby/
TLDR;Rubyists的结论是,dig
既易于使用,又可以更有力地保证值或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中阅读。它还不需要循环,这是此实现方式的一个缺点。
我认为这个问题需要在2018年进行一些刷新。可以在不使用任何库的情况下很好地完成此操作,Object.defineProperty()
并且可以按以下方式使用:
myVariable.safeGet('propA.propB.propC');
我认为这是安全的(和js道德的),因为MDN中已记录了的方法的writeable
和enumerable
定义,defineProperty
Object
功能定义如下:
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);
}
});
我整理了一个jsBin和控制台输出进行演示。请注意,在jsBin版本中,我还为空值添加了一个自定义异常。这是可选的,因此我将其排除在上面的最小定义之外。
欢迎改进
文章标签:babeljs , coffeescript , ecmascript-6 , javascript
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!
评论已关闭!