[英]Why do these snippets of JavaScript behave differently even though they both encounter an error?
var a = {} var b = {} try{ axy = be = 1 // Uncaught TypeError: Cannot set property 'y' of undefined } catch(err) { console.error(err); } console.log(be) // 1
var a = {} var b = {} try { axyz = be = 1 // Uncaught TypeError: Cannot read property 'y' of undefined } catch(err) { console.error(err); } console.log(be) // undefined
實際上,如果您正確讀取錯誤消息,則案例1和案例2會拋出不同的錯誤。
案例axy
:
無法設置未定義的屬性“y”
案例axyz
:
無法讀取未定義的屬性'y'
我想最好用簡單的英語逐步執行來描述它。
情況1
// 1. Declare variable `a` // 2. Define variable `a` as {} var a = {} // 1. Declare variable `b` // 2. Define variable `b` as {} var b = {} try { /** * 1. Read `a`, gets {} * 2. Read `ax`, gets undefined * 3. Read `b`, gets {} * 4. Set `bz` to 1, returns 1 * 5. Set `axy` to return value of `bz = 1` * 6. Throws "Cannot **set** property 'y' of undefined" */ axy = bz = 1 } catch(e){ console.error(e.message) } finally { console.log(bz) }
案例2
// 1. Declare variable `a` // 2. Define variable `a` as {} var a = {} // 1. Declare variable `b` // 2. Define variable `b` as {} var b = {} try { /** * 1. Read `a`, gets {} * 2. Read `ax`, gets undefined * 3. Read `axy`, throws "Cannot **read** property 'y' of undefined". */ axyz = bz = 1 } catch(e){ console.error(e.message) } finally { console.log(bz) }
在評論中, Solomon Tam發現了ECMA關於分配操作的文檔 。
當您在括號表示法中使用逗號運算符來查看在以下情況下執行哪些部分時,操作順序會更清晰:
var a = {} var b = {} try{ // Uncaught TypeError: Cannot set property 'y' of undefined a [console.log('x'), 'x'] [console.log('y'), 'y'] = (console.log('right hand side'), be = 1); } catch(err) { console.error(err); } console.log(be) // 1
var a = {} var b = {} try { // Uncaught TypeError: Cannot read property 'y' of undefined a [console.log('x'), 'x'] [console.log('y'), 'y'] [console.log('z'), 'z'] = (console.log('right hand side'), be = 1); } catch(err) { console.error(err); } console.log(be) // undefined
看看規格 :
生產
AssignmentExpression : LeftHandSideExpression = AssignmentExpression
的計算方法如下:
讓lref成為評估LeftHandSideExpression的結果。
讓rref成為評估AssignmentExpression的結果。
設rval為
GetValue(rref)
。如果......(無關緊要)拋出一個SyntaxError異常
調用
PutValue(lref, rval)
。
PutValue
拋出TypeError
:
設O為
ToObject(base)
。如果用參數P調用O的
[[CanPut]]
內部方法的結果為假,那么一個。 如果Throw為true,則拋出TypeError異常。
沒有什么可以被分配到的屬性undefined
-在[[CanPut]]
的內部方法undefined
將總是返回false
。
換句話說:解釋器解析左側,然后解析右側,如果左側的屬性無法分配, 則拋出錯誤。
當你這樣做
a.x.y = b.e = 1
左側成功解析 ,直到PutValue
; 在解析右側之后,才考慮.x
屬性求值為undefined
的事實。 解釋器將其視為“為屬性分配一些值”y“未定義”,並且分配給undefined
的屬性僅在PutValue
內PutValue
。
相反:
a.x.y.z = b.e = 1
解釋器永遠不會達到它試圖分配給z
屬性的程度,因為它首先必須將axy
解析為值。 如果axy
解析為一個值(甚至是undefined
),那axy
問題 - 如上所述, PutValue
會拋出一個錯誤。 但訪問 axy
會引發錯誤,因為在undefined
無法訪問屬性y
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.