ES6中是否存在null
- 安全属性访问(空传播/存在)运算符(ES2015 / JavaScript.next / Harmony),如中的 ?.
CoffeeScript 例如?或者它是否计划用于ES7?
var aThing = getSomething()
...
aThing = possiblyNull?.thing
这大致类似于:
if (possiblyNull != null) aThing = possiblyNull.thing
理想情况下,如果undefined
为aThing
,则解决方案不应(possiblyNull
}分配给null
答案 0 :(得分:77)
目前处于第1阶段的功能:可选链接。
https://github.com/tc39/proposal-optional-chaining
如果你想今天使用它,有一个Babel插件可以实现它。
https://github.com/davidyaha/ecmascript-optionals-proposal
更新(2017-08-01):如果您想使用官方插件,可以使用新变换尝试使用Babel 7的alpha版本。 您的里程可能会有所不同
https://www.npmjs.com/package/babel-plugin-transform-optional-chaining
答案 1 :(得分:48)
它不如?运算符,但要实现类似的结果,您可以这样做:
user && user.address && user.address.postcode
由于null
和undefined
都是 falsy 值(see this reference),因此&&
运算符后的属性只有先例才会被访问它不是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
答案 2 :(得分:31)
没有。您可以在JavaScript中使用lodash#get或类似内容。
答案 3 :(得分:12)
Vanilla替代安全财产访问
try { b = a.b.c.d.e } catch(e) {}
最简洁的条件赋值可能就是这个
{
"AWSTemplateFormatVersion": "2010-09-09",
"Parameters": {
"AGS": {
"Type": "String",
"AllowedPattern": "[a-zA-Z0-9_]+"
},
"Secret": {
"Type": "String",
"AllowedPattern": "[a-zA-Z0-9_]+",
"NoEcho": true
},
"SDLC": {
"Type": "String",
"AllowedValues": [
"D",
"I",
"J",
"Q",
"S",
"U",
"P",
"C"
]
},
"Component": {
"Type": "String",
"AllowedPattern": "[a-zA-Z0-9_]+"
},
"Topic": {
"Type": "String",
"AllowedPattern": "[a-zA-Z0-9_]+"
},
"TopicLambda": {
"Type": "String",
"AllowedPattern": "[a-zA-Z0-9_-]+"
}
},
"Resources": {
"BRIDGE2ESBTOPIC": {
"Type": "Custom::EnterpriseTopic",
"Version": 1,
"Properties": {
"ServiceToken": {
"Fn::Join": [
":",
[
"arn",
"aws",
"lambda",
{
"Ref": "AWS::Region"
},
{
"Ref": "AWS::AccountId"
},
"function",
{
"Ref": "TopicLambda"
}
]
]
},
"AGS": {
"Ref": "AGS"
},
"Secret": {
"Ref": "Secret"
},
"SDLC": {
"Ref": "SDLC"
},
"Component": {
"Ref": "Component"
},
"ResourceName": {
"Ref": "Topic"
}
}
}
},
//This will only output to CloudFormation console, not to command line.
"Outputs": {
"Topic": {
"Description" : "Topic created by this template",
"Value": {"Ref": "BRIDGE2ESBTOPIC"}
}
}
}
答案 4 :(得分:6)
不,ES6中没有空传播运算符。您必须使用其中一个known patterns。
您可以使用解构,但是:
({thing: aThing} = possiblyNull);
在ES7中添加这样的运算符有很多讨论(例如this),但没有一个真正起步。
答案 5 :(得分:6)
?.
和??
现在,您可以直接直接使用?.
(可选链接)来安全地测试是否存在。所有现代的浏览器都支持它。
??
(空位合并)可用于设置默认值(如果未定义或为空)。
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
?.
Browser Support-84%,2020年12月
-
当前正在将新的运算符添加到浏览器??=
,||=
和&&=
中。它们并不能完全满足您的要求,但根据您的代码目标,可能会导致相同的结果。
注意:这些在公共浏览器版本还中并不常见,但是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" }
Browser Support 2020年12月-79%
答案 6 :(得分:3)
从列表here开始,目前没有提议向Ecmascript添加安全遍历。因此,不仅没有很好的方法可以做到这一点,而且在可预见的未来不会被添加。
答案 7 :(得分:0)
一个安全的深度get方法似乎非常适合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('.'))
答案 8 :(得分:0)
// 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);
答案 9 :(得分:-1)
我知道这是一个JavaScript问题,但我认为Ruby会以所有要求的方式处理这个问题,所以我认为这是一个相关的参考点。
.&
,try
和&amp;&amp;有自己的优势和潜在的陷阱。这里有很好的选择:http://mitrev.net/ruby/2015/11/13/the-operator-in-ruby/
TLDR;
Rubyists的结论是dig
更容易在眼睛上,并且更有力地保证值或null
将被分配。
这是TypeScript中的一个简单的imeplementation:
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中同样很好用,如前面的答案所示。它也不需要循环,这是该实现的一个缺点。
答案 10 :(得分:-3)
我认为这个问题需要2018年的一些刷新。这可以很好地完成,没有任何库使用Object.defineProperty()
,可以按如下方式使用:
myVariable.safeGet('propA.propB.propC');
我认为这是安全的(和js-ethical),因为writeable
和enumerable
defineProperty
方法现在可用于Object
,因为documented in MDN }
下面的函数定义:
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版本中,我还为空值添加了自定义异常。这是可选的,所以我把它从上面的最小定义中删除了。
欢迎改进