簡體   English   中英

為什么這些JavaScript代碼片段表現不同,即使它們都遇到錯誤?

[英]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的計算方法如下:

  1. 讓lref成為評估LeftHandSideExpression的結果。

  2. 讓rref成為評估AssignmentExpression的結果。

  3. 設rval為GetValue(rref)

  4. 如果......(無關緊要)拋出一個SyntaxError異常

  5. 調用PutValue(lref, rval)

PutValue拋出TypeError

  1. 設O為ToObject(base)

  2. 如果用參數P調用O的[[CanPut]]內部方法的結果為假,那么

    一個。 如果Throw為true,則拋出TypeError異常。

沒有什么可以被分配到的屬性undefined -在[[CanPut]]的內部方法undefined將總是返回false

換句話說:解釋器解析左側,然后解析右側,如果左側的屬性無法分配, 拋出錯誤。

當你這樣做

a.x.y = b.e = 1

左側成功解析 ,直到PutValue ; 在解析右側之后,才考慮.x屬性求值為undefined的事實。 解釋器將其視為“為屬性分配一些值”y“未定義”,並且分配給undefined的屬性僅在PutValuePutValue

相反:

a.x.y.z = b.e = 1

解釋器永遠不會達到它試圖分配給z屬性的程度,因為它首先必須將axy解析為值。 如果axy解析為一個值(甚至是undefined ),那axy問題 - 如上所述, PutValue會拋出一個錯誤。 訪問 axy會引發錯誤,因為在undefined無法訪問屬性y

請考慮以下代碼:

 var a = {}; axy = console.log("evaluating right hand side"), 1; 

的執行代碼如下所需的步驟粗線條參考

  1. 評估左側。 要記住兩件事:
    • 評估表達式與獲取表達式的值不同。
    • 評估屬性訪問REF例如axy返回一個引用參考文獻 ,包括基值ax (未定義)和引用的名稱( y )。
  2. 評估右側。
  3. 獲取步驟2中獲得的結果值。
  4. 將步驟1中獲得的參考值設置為步驟3中獲得的值,即將undefined的屬性y設置為該值。 這應該拋出一個TypeError異常引用

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM