用空对象反复 OR
在编写引用可能存在或不存在的属性/子属性的 HTML 时,我不能没有 Elvis。
我们不能写
this.myForm?.name?.first_name
我猜负责 ES 的人可能大部分时间都在实际编写 JS,而不是编写访问对象属性的前端 HTML,因此他们对为什么任何人都需要安全导航感到困惑。
他们争辩说“没有人需要它”、“它可以让错误保持沉默,从而可能会在以后咬你”和“你会如何解释x?(y)?”
当我等待未来的 ES 规范包含 Elvis 运算符时,我的解决方案如下:
(((this.myForm || {}).name || {}).first_name )
简而言之,在值可能为undefined 的每个阶段,您将OR 与{} 结合起来,这样未定义的对象就变成了一个空对象。一旦将整个内容放入括号中,您就可以安全地尝试提取它的属性,因为您尝试从 {} 提取的任何属性都只是 undefined 而不是实际错误。
当您有多个层时,它确实会有点难看,但在许多情况下,它比必须使用一系列 && 来逐步降低对象的层级更难看。
对于数组访问,或它与一个空数组
如果导航到一个数组中,例如,如果表单有很多名称并且您想选择第一个,方法类似:
((((this.myForm || {}).names || [])[0] || {}).first_name )
如果链中的某些东西是 0 或 "" 会发生什么?
假设您希望从this.myForm.names[0].first_name 中读取值“John”。
通常会触发错误的典型情况是根本没有对象this.myForm。我上面描述的公式不会出错,而是可以工作,并被解释为{}.first_name,即undefined(但不是错误)。
现在想象一个敌对的人偷偷地将 this.myForm 设置为 0 或 "" 或 {}。我们现在会看到错误吗?不,因为值 0 或 "" 被 Javascript 认为是虚假的,而 {} 是真实的,但它本身就是 {},所以 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)