การมอบหมายทางซ้ายหลายครั้งพร้อม JavaScript


186
var var1 = 1,
    var2 = 1,
    var3 = 1;

นี่เทียบเท่ากับสิ่งนี้:

var var1 = var2 = var3 = 1;

ฉันค่อนข้างแน่ใจว่านี่คือลำดับของตัวแปรที่กำหนดไว้: var3, var2, var1 ซึ่งจะเท่ากับ:

var var3 = 1, var2 = var3, var1 = var2;

มีวิธีการยืนยันใน JavaScript หรือไม่? การใช้ profiler อาจเป็นไปได้?


6
การกำหนดเกิดขึ้นขวาเป็นซ้าย ตัวดำเนินการจาวาสคริปต์
neaumusic

ใช้กับฉันได้this.var1 = this.var2 = this.var3 = 1ไหมถ้าฉันใช้?
Gangadhar JANNU

คำตอบ:


404

อันที่จริงแล้ว

var var1 = 1, var2 = 1, var3 = 1;

คือไม่ได้เทียบเท่ากับ:

var var1 = var2 = var3 = 1;

ความแตกต่างอยู่ในขอบเขต:

function good() {
  var var1 = 1, var2 = 1, var3 = 1;
}

function bad() {
  var var1 = var2 = var3 = 1;
}

good();
console.log(window.var2); // undefined

bad();
console.log(window.var2); // 1. Aggh!

จริงๆแล้วนี่แสดงให้เห็นว่าการมอบหมายนั้นเชื่อมโยงกันอย่างถูกต้อง badตัวอย่างเทียบเท่ากับ:

var var1 = (window.var2 = (window.var3 = 1));

44
แดงนั่นคือสิ่งที่ไม่คาดคิด ขอบคุณสำหรับเคล็ดลับฉันจะระวังสิ่งนั้น
David Calhoun

10
@ SkinnyG33k เพราะถูกต้องแล้ว ดังนั้นมันจะแยกขวาสุดก่อนซ้ายสุด เพื่อให้var var1=var2เกิดขึ้นหลังจากและหลังvar3 = 1 var2 = var3เป็นอย่างไรvar3=1; var2=var3; var var1=var2
gcb

12
ที่ควรทราบ: หากคุณรู้ว่าคุณต้องการทำสิ่งนี้ล่วงหน้าคุณยังสามารถแยกคำจำกัดความจากงานที่มอบหมายได้ ดังนั้น: var v1, v2, v3;หลังจากนั้น: v1 = v2 = v3 = 6;พวกเขาจะยังอยู่ในขอบเขตของท้องถิ่น นับตั้งแต่เดวิดพูดถึงการแจ้งเตือนสิ่งนี้จะทำงานได้ตามที่คาดไว้ (ถ้า pre-var'd):alert(v1 = v2 = v3 = 6);
ShawnFumo

3
เผง แต่ถ้าเราปฏิบัติตามแนวทางปฏิบัติที่ดีที่สุดทั่วไปในกรณีนี้โดยการประกาศตัวแปรของเราที่ด้านบนเราสามารถป้องกันความผิดพลาดที่ไม่ต้องการและหลีกเลี่ยงตัวแปรท้องถิ่นที่รั่วไหลไปสู่ขอบเขตทั่วโลก ดู: jsfiddle.net/gleezer/r9Mu8/1
โนบิตะ

1
"แดงนั่นคาดไม่ถึง" ทำไมสิ่งนี้ถึงไม่คาดคิด ภาษาส่วนใหญ่ต้องการให้คุณประกาศตัวแปรก่อนการใช้งาน JavaScript ไม่แตกต่างกันหากคุณละเลยที่จะประกาศตัวแปรของคุณมันเป็นค่าเริ่มต้นไปที่วัตถุหน้าต่างทั่วโลก เริ่มใช้ 'use เข้มงวด' ใน javascript ของคุณและคุณจะกลายเป็นโปรแกรมเมอร์ JavaScript ที่ดีขึ้น
cchamberlain

20

การกำหนดใน javascript ทำงานจากขวาไปซ้าย var var1 = var2 = var3 = 1;.

หากค่าของตัวแปรใด ๆ เหล่านี้อยู่1หลังคำสั่งนี้จะต้องเริ่มต้นด้วยเหตุผลทางด้านขวามิฉะนั้นค่าหรือvar1และvar2จะไม่ถูกกำหนด

คุณสามารถคิดได้ว่ามันจะเทียบเท่ากับvar var1 = (var2 = (var3 = 1));ที่มีการประเมินชุดวงเล็บภายในมากที่สุดก่อน


1
ขอบคุณสิ่งนี้ช่วยได้แน่นอน ช่วยในการคิดในแง่ของข้อผิดพลาดอะไรที่จะถูกส่งออกหากมีการประเมินนอกเหนือจากขวาไปซ้าย (ในกรณีนี้ข้อผิดพลาดน่าจะเป็นที่ var1 / var2 ไม่ได้ถูกกำหนด)
David Calhoun

5
อันที่จริงมันเป็นข้อผิดพลาดทางไวยากรณ์ คุณไม่สามารถมีได้ทันทีหลังจากที่( varการลบวงเล็บด้านนอกออกทำให้สามารถคอมไพล์ได้โดยไม่มีข้อผิดพลาด, var var1 = (var2 = (var3 = 1));. ในเวลาที่ฉันรู้สึกว่ามันไม่ได้แสดงให้เห็นถึงจุดที่ค่อนข้างดี แต่ฉันคิดว่ามันเหมือนกัน
Justin Johnson

var var1 = var2 = var3 = 1;. เท่ากับ var var3 = 1; var var2 = var3; var var1 = var2;
xgqfrms

8

var var1 = 1, var2 = 1, var3 = 1;

ในกรณีนี้ varคำหลักสามารถใช้ได้กับตัวแปรทั้งสามตัว

var var1 = 1,
    var2 = 1,
    var3 = 1;

ซึ่งไม่เท่ากับสิ่งนี้:

var var1 = var2 = var3 = 1;

ในกรณีนี้อยู่ด้านหลังvarคีย์เวิร์ดscreen จะใช้ได้เฉพาะvar1เนื่องจากการยกตัวแปรและการแสดงออกที่เหลือจะได้รับการประเมินตามปกติดังนั้นตัวแปรvar2, var3จึงกลายเป็นกลม

Javascript ใช้รหัสนี้ตามลำดับนี้:

/*
var 1 is local to the particular scope because of var keyword
var2 and var3 will become globals because they've used without var keyword
*/

var var1;   //only variable declarations will be hoisted.

var1= var2= var3 = 1; 

8
a = (b = 'string is truthy'); // b gets string; a gets b, which is a primitive (copy)
a = (b = { c: 'yes' }); // they point to the same object; a === b (not a copy)

(a && b)มีเหตุผล(a ? b : a)และทำตัวเหมือนการคูณ (เช่น!!a * !!b)

(a || b)มีเหตุผล(a ? a : b)และมีพฤติกรรมเหมือนการเพิ่ม (เช่น!!a + !!b)

(a = 0, b)สั้นสำหรับไม่สนใจถ้าaเป็นความจริงส่งกลับโดยปริยายb


a = (b = 0) && "nope, but a is 0 and b is 0"; // b is falsey + order of operations
a = (b = "b is this string") && "a gets this string"; // b is truthy + order of ops

จาวาสคริปต์ดำเนินการก่อนหน้า (ลำดับของการดำเนินการ)

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


ในที่สุดคุณอาจต้องการ 'thunks' มากกว่าค่าฮาร์ดโค้ดและสำหรับฉันแล้ว thunk เป็นทั้งฟังก์ชันและค่าผลลัพธ์ (สิ่งเดียวกัน)

const windowInnerHeight = () => 0.8 * window.innerHeight; // a thunk

windowInnerHeight(); // a thunk

4

ลองสิ่งนี้:

var var1=42;
var var2;

alert(var2 = var1); //show result of assignment expression is assigned value
alert(var2); // show assignment did occur.

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

เป็นไปตามหลักเหตุผลว่าต้องมีการผูกมัดจากขวาไปซ้าย อย่างไรก็ตามเนื่องจากนี่เป็นอะตอมมิกทั้งหมดของจาวาสคริปต์ (ไม่มีเธรด) เอ็นจิ้นเฉพาะอาจเลือกที่จะปรับให้เหมาะสมแตกต่างกันเล็กน้อย


1
ขอบคุณสำหรับคำตอบ. ฉันคิดว่าฉันกำลังมองหาวิธีที่จะใช้การแจ้งเตือนในขณะที่ยังคงรักษาโครงสร้างการมอบหมายหลายรายการ (a = b = c) แต่ฉันไม่คิดว่าเป็นไปได้
David Calhoun

1
ข้อความส่วนบุคคลเช่นนั้นในจาวาสคริปต์ (และแม้ว่าจะมีหลายนิพจน์ว่าทั้งหมดทำงานได้กับข้อความเดี่ยว) สามารถพิจารณาได้ว่าเป็นอะตอมมิก คุณต้องแยกมันออก
Joel Coehoorn

1

ตอนนี้มันชัดเจนแล้วว่าพวกเขาไม่เหมือนกัน วิธีในการรหัสนั่นคือ

var var1, var2, var3
var1 = var2 = var3 = 1

แล้วการให้คำตอบล่ะ? เหมือนกันกับ var อย่าปล่อยให้การจัดกลุ่มให้คุณสับสนเนื่องจากขอบเขตบล็อก

let var1 = var2 = 1 // here var2 belong to the global scope

เราสามารถทำสิ่งต่อไปนี้:

let v1, v2, v3
v1 = v2 = v3 = 2

หมายเหตุ: btw ฉันไม่แนะนำให้ใช้การกำหนดหลายครั้งหรือแม้แต่การประกาศหลายครั้งในบรรทัดเดียวกัน


-3

coffee-script สามารถบรรลุสิ่งนี้ด้วยความมั่นใจในตนเอง ..

for x in [ 'a', 'b', 'c' ] then "#{x}" : true

[ { a: true }, { b: true }, { c: true } ]


7
นี่ไม่ได้ตอบคำถามจริงๆ โปรดอ่านคำถามอีกครั้ง
Martin

30
ใครสนใจเกี่ยวกับ coffeescript
neaumusic
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.