การมอบหมายงานด้วยเครื่องหมายจุลภาคได้ผลหรือไม่?


108

ทำไมถึงaaa = 1,2,3ทำงานและตั้งค่าaaaเป็น1?

ทำไมไม่var bbb = 1,2,3ทำงาน

ทำไมถึงvar bbb = (1,2,3)ทำงานและตั้งค่าbbbเป็น3?

ตัวอย่างเซสชันคอนโซล


9
คุณได้รับข้อผิดพลาดทางไวยากรณ์เนื่องจากชื่อตัวแปรไม่ได้รับอนุญาตให้ขึ้นต้นด้วยตัวเลข var a1,a2,a3;ก็จะประกาศตัวแปรท้องถิ่นสามตัว
Jared Farrish

คำตอบ:


200

มีจำนวนมากเกิดขึ้นที่นี่ แต่โดยทั่วไปมันลงมาถึงผู้ประกอบการจุลภาค

ตัวดำเนินการลูกน้ำจะประเมินตัวถูกดำเนินการทั้งสอง (จากซ้ายไปขวา) และส่งคืนค่าของตัวถูกดำเนินการที่สอง


รหัสนี้:

aaa = 1,2,3

เทียบเท่ากับ:

aaa = 1;
2;
3;

ดังนั้นaaaมีการประกาศโดยปริยายและกำหนดค่าเป็น 1 โปรดสังเกตว่าเอาต์พุตบนคอนโซลเป็นผลลัพธ์ของคำสั่งสุดท้าย 3


รหัสนี้:

var bbb = 1,2,3

เป็นข้อผิดพลาดทางไวยากรณ์เนื่องจากใช้เครื่องหมายจุลภาคในการประกาศตัวแปรเพื่อประกาศตัวแปรหลายตัวในบรรทัดเดียว ดังที่บทความ MDN ชี้ให้เห็น

โปรดสังเกตว่าเครื่องหมายจุลภาคในvarคำสั่งไม่ใช่ตัวดำเนินการลูกน้ำเนื่องจากไม่มีอยู่ในนิพจน์ แต่เป็นอักขระพิเศษในvarคำสั่งที่จะรวมหลาย ๆ ตัวเป็นหนึ่งเดียว

ดังนั้นรหัสนี้จึงเทียบเท่ากับ:

var bbb = 1;
var 2;
var 3;

แน่นอนว่า2ไม่ใช่ตัวระบุที่ถูกต้องดังนั้นจึงล้มเหลวในตอนนั้น


รหัสนี้:

var bbb = (1,2,3)

คล้ายกับค่าแรกมากยกเว้นเนื่องจากค่าตัวเลขอยู่ในวงเล็บจึงได้รับการประเมินก่อน ดังนั้นนี่จึงน่าเกลียดเทียบเท่ากับ:

1;
2;
var bbb = 3;

17
ยิ่งไปกว่านั้น=อินvar bbb = 1;ไม่เหมือนกับ=ในaaa = 1;- พวกเขามาจากการผลิตที่แตกต่างกัน (Initialiser vs AssignmentExpression) ในไวยากรณ์และเพิ่งเกิดขึ้นเพื่อใช้โทเค็นเดียวกัน
Ryan Cavanaugh

7
คำอธิบายที่ดีมาก สิ่งที่ไม่ชัดเจนอย่างสิ้นเชิงคือa = 1, 2, 3สามารถใส่วงเล็บ(a = 1), 2, 3ซึ่งประเมินเป็นa = 1; 2; 3(และส่งกลับ 3 เช่นb = (a = 1, 2, 3)จะกำหนด 3 ให้ b) ในทางตรงกันข้ามa = (1, 2, 3)ประเมินเป็น1; 2; a = 3และส่งกลับ 3
CompuChip

MDN พูดอย่างไรเกี่ยวกับ parens ในการกำหนดตัวแปรและเหตุใดจึงกลับกัน ฉันไม่พบเอกสาร
Brian

@staticx ไม่มีอะไรทำ 'ย้อนกลับ' จริงๆ วงเล็บจะได้รับการประเมินก่อน เช่นเดียวกับเมื่อคุณมี(1 + 2) * 3ค่า1 + 2จะถูกประเมินก่อนและผลลัพธ์ของนิพจน์นั้นจะถูกแทนที่กลับเป็นนิพจน์ด้านนอกสำหรับการประเมินที่เหลือ
pswg

9

จุลภาคมีประโยชน์หลายอย่างใน Javascript ในนิพจน์:

a = 1, 2, 3;

มันเป็นโอเปอเรเตอร์ที่ส่งกลับอาร์กิวเมนต์ขวามือ แต่ยังเป็นส่วนหนึ่งของไวยากรณ์ของvarการประกาศซึ่ง ได้แก่ :

var var1 [ = val1 ], var2 [ = val2 ], var3 [ = val3 ], ...;

(ซึ่ง[...]หมายความว่าส่วนนั้นเป็นทางเลือก) varการประกาศของคุณไม่มีชื่อตัวแปรหลังเครื่องหมายจุลภาคดังนั้นจึงไม่แยกวิเคราะห์ คุณจะได้รับเอฟเฟกต์ที่คุณต้องการด้วย:

var a = (1, 2, 3);

วงเล็บบังคับให้ใช้เครื่องหมายจุลภาคเป็นตัวดำเนินการแทนที่จะใช้ตัวคั่นระหว่างการประกาศตัวแปร


7

ในตัวอย่างของคุณเครื่องหมายจุลภาคถูกใช้ในสองบริบท:

var คำให้การ

ไวยากรณ์ของvarคำสั่งคือ:

var varname1 [= value1 [, varname2 [, varname3 ... [, varnameN]]]];

ในที่นี้จะใช้จุลภาคเพื่อแยกคู่ชื่อ - ค่าตัวแปร สิ่งต่อไปนี้จะใช้ไม่ได้เนื่องจากชื่อตัวแปรไม่สามารถขึ้นต้นด้วยตัวเลข (ดูชื่อตัวระบุ ):

var bbb = 1, 2, 3;
// SyntaxError: Unexpected number

ตัวดำเนินการจุลภาค

ตัวดำเนินการลูกน้ำจะประเมินตัวถูกดำเนินการทั้งสอง (จากซ้ายไปขวา) และส่งคืนค่าของตัวถูกดำเนินการที่สอง นิพจน์ต่อไปนี้ทำงานดังนี้:

aaa = 1, 2, 3;
  • aaa = 1, 2 ให้ผล 2
    • หมายเหตุที่aaa = 1ได้รับการประเมินก่อนเนื่องจาก=มีลำดับความสำคัญสูงกว่า,
  • 2, 3 ผลตอบแทน 3
var bbb = (1, 2, 3);
  • นิพจน์(1, 2, 3)ให้ผล3ตามที่อธิบายไว้ข้างต้น
  • ตัวแปรbbbถูกกำหนดค่า3

2
aaa = 1, 2, 3=> ตัวดำเนินการลูกน้ำใช้เพื่อแยก 3 คำสั่งต่อไปนี้: aaa=1, 2และ3 . ผลลัพธ์ของตัวดำเนินการลูกน้ำคือค่าของคำสั่งสุดท้าย 3 อย่างไรก็ตาม aaa ถูกกำหนดค่าเป็น 1 ดังที่เห็นได้ชัดเจนจากภาพหน้าจอของ OP เหตุผลนี้คือลำดับความสำคัญของตัวดำเนินการโดยตัวดำเนินการจุลภาคมีลำดับความสำคัญต่ำสุด
Tibos

1

ในกรณีแรก:

aaa = 1,2,3

เครื่องหมายจุลภาคทำหน้าที่เป็นตัวคั่นนิพจน์ ดำเนินการมอบหมายให้aaaแล้วคำนวณ2และทิ้งมันจากนั้นจะคำนวณ3และทิ้งมัน

ในวินาที:

var bbb = 1,2,3

varคำหลักบอกคอมไพเลอร์จาวาสคริปต์ที่สิ่งต่อไปหลังจากที่,ควรจะเป็นอีกชื่อตัวแปร มันหาไม่เจอก็เลยตายมุข

var bbb = (1,2,3)

ที่นี่คอมไพลเลอร์จะประเมิน1และเพิกเฉยก่อน จากนั้นจะประเมิน2และไม่สนใจมัน จากนั้นจะประเมิน3และที่เหลืออยู่ในสแต็กจึงถูกกำหนดให้bbb

แม้ว่าการใช้เครื่องหมายจุลภาคเพื่อแยกนิพจน์ไม่ใช่เรื่องปกติ แต่บางครั้งก็มีประโยชน์ในเรื่องต่างๆเช่นforรูปลักษณ์

for (i = 0, l = 10; i < l; i++) {
  console.log(i);
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.