用空对象重复OR运算
在编写引用可能存在或不存在的属性/子属性的HTML时,我无法离开Elvis。
我们不能写成:
this.myForm?.name?.first_name
我猜ES负责人可能大部分时间都在编写JS,而不是编写访问对象属性的前端HTML代码,因此他们对为什么需要安全导航感到困惑。
他们认为“没有人需要它”,“它允许错误保持沉默,可能会在以后造成问题”和“你如何解释 x?(y)
?”
在等待未来的ES规范包含Elvis操作符的同时,我的解决方案如下:
(((this.myForm || {}).name || {}).first_name )
简而言之,在每个可能出现
undefined
的阶段,您都需要将其与
{}
进行
OR
运算,以便将未定义变为空对象。一旦您将整个内容放入括号中,就可以安全地尝试从中提取属性,因为您尝试从
{}
提取的任何属性都只是
undefined
,而不是实际错误。
当您有多个层级时,它确实会变得有点丑陋,但在许多情况下,它比使用一系列
&&
逐步遍历对象的级别要少丑陋。
对于数组访问,请将其与空数组
[]
进行
OR
运算。
如果要导航到一个数组,例如如果表单有很多名称并且您想选择第一个,则方法类似:
((((this.myForm || {}).names || [])[0] || {}).first_name )
如果链中的某个值为0或""会发生什么?
假设您希望从 this.myForm.names[0].first_name
读取值 "John"。
通常情况下,触发错误的典型情况是没有对象 this.myForm
。但是,在我描述的公式中,不会出现错误,而会被解释为 {}.first_name
,即 undefined
(但不是错误)。
现在想象一下,一个敌对的人已经将 this.myForm
偷偷设置为0或""或{}。我们是否会看到错误?不会,因为Javascript认为值0或""为假,{}为真,但是本身就是{},所以 this.myForm || {}
求值为{},链的其余部分按照默认设置运行,该方法仍然起作用,返回 undefined
而不是错误。
示例
console.log("Each example shows first the result WITH the workaround, and then WITHOUT.")
console.log("a. This should work normally.")
a = { myForm:{ names:[ { first_name:"John", surname:"Smith"}]} };
console.log(a.myForm.names[0].first_name)
console.log ((((a.myForm || {}).names || [])[0] || {}).first_name )
console.log("b. We have removed the first_name property. This still works.")
b = { myForm:{ names:[ { surname:"Smith"}]} };
console.log(b.myForm.names[0].first_name)
console.log ((((b.myForm || {}).names || [])[0] || {}).first_name )
console.log("c. We have removed the entire 'names' array. This is fixed by the workaround, but gives an error if run without the workaround.")
c = { myForm:{ } };
console.log ((((c.myForm || {}).names || [])[0] || {}).first_name )
console.log(c.myForm.names[0].first_name)
console.log("d. Now the whole root object is empty. Again the workaround gets around this, but without the workaround, we get an error.")
d = { };
console.log ((((d.myForm || {}).names || [])[0] || {}).first_name )
console.log(d.myForm.names[0].first_name)
||
。 - Drazen Bjelovuk