ลำดับของการดำเนินการจะชัดเจนขึ้นเมื่อคุณใช้ตัวดำเนินการลูกน้ำภายในสัญกรณ์วงเล็บเพื่อดูว่าส่วนใดถูกดำเนินการเมื่อ:
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'), b.e = 1);
} catch(err) {
console.error(err);
}
console.log(b.e) // 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'), b.e = 1);
} catch(err) {
console.error(err);
}
console.log(b.e) // undefined
ดูข้อมูลจำเพาะ :
การผลิตAssignmentExpression : LeftHandSideExpression = AssignmentExpression
ได้รับการประเมินดังนี้:
ให้ lref เป็นผลลัพธ์ของการประเมิน LeftHandSideExpression
ให้ rref เป็นผลลัพธ์ของการประเมิน AssignmentExpression
GetValue(rref)
อนุญาตเป็น rval
โยนข้อยกเว้น SyntaxError ถ้า ... (ไม่เกี่ยวข้อง)
โทรPutValue(lref, rval)
.
PutValue
คือสิ่งที่พ่นTypeError
:
ToObject(base)
ให้เป็น O
หากผลลัพธ์ของการเรียก[[CanPut]]
เมธอดภายในของ O ด้วยอาร์กิวเมนต์ P เป็นเท็จดังนั้น
ก. ถ้า Throw เป็นจริงให้โยนข้อยกเว้น TypeError
ไม่มีอะไรที่สามารถกำหนดให้กับทรัพย์สินของundefined
- The [[CanPut]]
วิธีการภายในของมักจะกลับมาundefined
false
กล่าวอีกนัยหนึ่ง: ล่ามจะแยกวิเคราะห์ทางด้านซ้ายจากนั้นแยกวิเคราะห์ทางด้านขวาจากนั้นจะแสดงข้อผิดพลาดหากไม่สามารถกำหนดคุณสมบัติทางด้านซ้ายมือให้ได้
เมื่อคุณทำ
a.x.y = b.e = 1
ด้านซ้ายมือจะถูกแยกวิเคราะห์เรียบร้อยแล้วจนกว่าPutValue
จะถูกเรียก ความจริงที่ว่า.x
คุณสมบัติที่ประเมินundefined
เป็นจะไม่ได้รับการพิจารณาจนกว่าจะมีการแยกวิเคราะห์ด้านขวามือ ล่ามจะมองว่าเป็น "กำหนดค่าบางอย่างให้กับคุณสมบัติ" y "ของไม่ได้กำหนด" และกำหนดให้กับคุณสมบัติที่undefined
โยนเข้าไปข้างในPutValue
เท่านั้น
ในทางตรงกันข้าม:
a.x.y.z = b.e = 1
ล่ามจะไม่ไปถึงจุดที่พยายามกำหนดให้กับz
คุณสมบัติเพราะต้องแก้ไขa.x.y
เป็นค่าก่อน หากa.x.y
แก้ไขเป็นค่า (แม้ถึงundefined
) ก็จะใช้ได้ - ข้อผิดพลาดจะถูกโยนเข้าไปข้างในPutValue
เหมือนข้างบน แต่การเข้าถึง a.x.y
โยนข้อผิดพลาดเพราะคุณสมบัติที่ไม่สามารถเข้าถึงได้บนy
undefined
b.z = 1
และb.e = 1
ดำเนินการก่อน (ให้สิทธิ์การเชื่อมโยงบน=
) จากนั้นa.x.y.z = ...
ดำเนินการและล้มเหลว เหตุใดการb
มอบหมายจึงส่งผ่านในกรณีหนึ่ง แต่ไม่ผ่านอีกกรณีหนึ่ง