การแพร่กระจายของวัตถุกับ Object.assign


396

สมมติว่าฉันมีoptionsตัวแปรและฉันต้องการตั้งค่าเริ่มต้นบางอย่าง

ประโยชน์ / ข้อเสียของสองตัวเลือกนี้คืออะไร

ใช้การแพร่กระจายวัตถุ

options = {...optionsDefault, ...options};

หรือใช้ Object.assign

options = Object.assign({}, optionsDefault, options);

นี่คือความมุ่งมั่นที่ทำให้ฉันประหลาดใจ


4
อย่างแรกคือไวยากรณ์ใหม่ที่เสนอและไม่ได้เป็นส่วนหนึ่งของ ES6 ดังนั้นจึงขึ้นอยู่กับมาตรฐานที่คุณต้องการยึดติด
loganfsmyth

5
กำหนด " ดีที่สุด " (อย่างระมัดระวังอย่าท้ายด้วยคำถามตามความคิดเห็น :-)
Amit

1
อาจขึ้นอยู่กับว่าคุณต้องการสนับสนุนอย่างไรหากทำงานในสภาพแวดล้อมที่ไม่มีการสนับสนุนดั้งเดิม ไวยากรณ์ที่คุณอาจจะสามารถรวบรวมได้ วัตถุหรือวิธีการที่คุณอาจจำเป็นต้องใช้ polyfill
JMM

6
นอกเหนือจากปัญหาความเข้ากันได้ Object.assign สามารถกลายพันธุ์วัตถุต้นฉบับซึ่งมีประโยชน์ การแพร่กระจายไม่สามารถ
pstanton

2
เพื่อชี้แจงความคิดเห็น @ pstanton ของ - object.assign สามารถปรับเปลี่ยนวัตถุเป้าหมายที่มีอยู่(เขียนทับคุณสมบัติจากแหล่งที่มาในขณะที่ปล่อยให้คุณสมบัติอื่น ๆ เหมือนเดิม); มันไม่ได้สัมผัสวัตถุต้นฉบับ ฉันอ่าน "วัตถุต้นฉบับ" ของเขาเป็น "แหล่งวัตถุ" ก่อนดังนั้นจึงเขียนบันทึกนี้ให้คนอื่นที่อ่านผิดเหมือนกัน :)
ToolmakerSteve

คำตอบ:


328

สิ่งนี้ไม่จำเป็นต้องละเอียดถี่ถ้วน

สเปรดไวยากรณ์

options = {...optionsDefault, ...options};

ข้อดี:

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

  • verbose น้อย

ข้อเสีย:

  • เมื่อคำตอบนี้ถูกเขียนขึ้นครั้งแรกนี่เป็นข้อเสนอไม่ใช่มาตรฐาน เมื่อใช้ข้อเสนอให้พิจารณาสิ่งที่คุณจะทำถ้าคุณเขียนโค้ดด้วยในตอนนี้และจะไม่ได้รับมาตรฐานหรือการเปลี่ยนแปลงเมื่อมันเข้าสู่มาตรฐาน สิ่งนี้นับเป็นมาตรฐานใน ES2018

  • ตามตัวอักษรไม่ใช่แบบไดนามิก


Object.assign()

options = Object.assign({}, optionsDefault, options);

ข้อดี:

  • มาตรฐาน

  • พลวัต ตัวอย่าง:

    var sources = [{a: "A"}, {b: "B"}, {c: "C"}];
    options = Object.assign.apply(Object, [{}].concat(sources));
    // or
    options = Object.assign({}, ...sources);

ข้อเสีย:

  • รายละเอียดเพิ่มเติม
  • หากการเขียนรหัสสำหรับการดำเนินการในสภาพแวดล้อมที่ไม่มีการสนับสนุนพื้นเมืองคุณจำเป็นต้อง polyfill

นี่คือความมุ่งมั่นที่ทำให้ฉันประหลาดใจ

ไม่เกี่ยวข้องโดยตรงกับสิ่งที่คุณถาม รหัสนั้นไม่ได้ใช้Object.assign()มันใช้รหัสผู้ใช้ ( object-assign) ที่ทำสิ่งเดียวกัน ดูเหมือนว่าพวกเขาจะรวบรวมรหัสนั้นด้วย Babel (และรวมเข้ากับ Webpack) ซึ่งเป็นสิ่งที่ฉันพูดถึง: ไวยากรณ์ที่คุณสามารถรวบรวมได้ เห็นได้ชัดว่าพวกเขาต้องการที่จะรวมobject-assignเป็นพึ่งพาที่จะเข้าไปในงานสร้างของพวกเขา


15
มันอาจจะเป็นที่น่าสังเกตว่าส่วนที่เหลือวัตถุแพร่กระจายได้ย้ายไป 3 ขั้นตอนเพื่อให้มีแนวโน้มที่จะเป็นมาตรฐานในอนาคตtwitter.com/sebmarkbage/status/781564713750573056
williaster

11
@JMM ฉันไม่แน่ใจว่าฉันเห็น "รายละเอียดเพิ่มเติม" เป็นข้อเสีย
DiverseAndRemote.com

6
@ โอเคดีฉันเดาว่าคุณเพิ่งพิสูจน์ว่ามันเป็นความเห็น :) ถ้ามีคนไม่รู้จักข้อได้เปรียบนั้นก็ใช่พวกเขาก็สามารถObject.assign()ใช้ได้ หรือคุณสามารถวนซ้ำวัตถุและอุปกรณ์ประกอบฉากของพวกเขาด้วยตนเองกำหนดให้กับเป้าหมายและทำให้มันละเอียดยิ่งขึ้น: P
JMM

7
ดังที่ @JMM ถูกกล่าวถึงตอนนี้อยู่ในข้อมูลจำเพาะ ES2018 node.green/#ES2018-features-object-rest-spread-properties
Sebastien H.

2
"ทุก ๆ ไบต์มีค่า" นั่นคือสิ่งที่ minimizers / uglify ใช้สำหรับ @yzorg
DiverseAndRemote.com

171

สำหรับการอ้างอิงส่วนที่เหลือ / สเปรดถูกสรุปใน ECMAScript 2018 เป็นสเตจ 4 ข้อเสนอสามารถพบได้ที่นี่ที่นี่

สำหรับการรีเซ็ตวัตถุส่วนใหญ่และการแพร่กระจายทำงานในลักษณะเดียวกันความแตกต่างที่สำคัญคือการแพร่กระจายกำหนดคุณสมบัติในขณะที่ Object.assign () ตั้งค่าพวกเขากำหนดให้พวกเขา ซึ่งหมายถึง Object.assign () เรียกใช้ตัวตั้งค่า

เป็นมูลค่าการจำที่นอกเหนือจากนี้แผนที่ส่วนที่เหลือ / การแพร่กระจาย 1: 1 แผนที่ไปยัง Object.assign () และทำหน้าที่แตกต่างกันไปในการแพร่กระจายอาร์เรย์ (iterable) ตัวอย่างเช่นเมื่อการแพร่กระจายค่าอาร์เรย์เป็นศูนย์จะแพร่กระจาย อย่างไรก็ตามการใช้การกระจายออบเจ็กต์ค่าศูนย์จะถูกกระจายไปอย่างเงียบ ๆ เพื่ออะไร

Array (Iterable) Spread ตัวอย่าง

const x = [1, 2, null , 3];
const y = [...x, 4, 5];
const z = null;

console.log(y); // [1, 2, null, 3, 4, 5];
console.log([...z]); // TypeError

ตัวอย่างการกระจายวัตถุ

const x = null;
const y = {a: 1, b: 2};
const z = {...x, ...y};

console.log(z); //{a: 1, b: 2}

สิ่งนี้สอดคล้องกับวิธีการทำงานของ Object.assign () ทั้งสองแยกค่า null ที่ไม่มีข้อผิดพลาดโดยไม่มีข้อผิดพลาด

const x = null;
const y = {a: 1, b: 2};
const z = Object.assign({}, x, y);

console.log(z); //{a: 1, b: 2}

10
นี่ควรเป็นคำตอบที่เลือก
Evan Plaice

4
นี่ควรเป็นคำตอบ ... มันเป็นอนาคตแล้ว
Zachary Abresch

1
นี่คือคำตอบที่ถูกต้อง ความแตกต่างหลักคือObject.assignจะใช้ตัวตั้งค่า Object.assign({set a(v){this.b=v}, b:2}, {a:4}); // {b: 4}vs.{...{set a(v){this.b=v}, b:2}, ...{a:4}}; // {a: 4, b: 2}
David Boho

1
"อนาคตคือตอนนี้!" - George Allen Tomorrow สายเกินไป
ruffin

1
การสาธิตการจัดการค่า null ต่างกันคือ "แอปเปิ้ลและส้ม" - ไม่ใช่การเปรียบเทียบที่มีความหมาย ในกรณีที่อาร์เรย์เป็นโมฆะองค์ประกอบของอาร์เรย์ ในกรณีการแพร่กระจาย, null เป็นวัตถุทั้งหมด การเปรียบเทียบที่ถูกต้องจะเป็นสำหรับ x จะมีคุณสมบัติ nullconst x = {c: null}; : ซึ่งในกรณีนี้ AFAIK //{a: 1, b: 2, c: null}เราจะเห็นพฤติกรรมเช่นเดียวกับอาร์เรย์:
ToolmakerSteve

39

ฉันคิดว่าหนึ่งความแตกต่างใหญ่ระหว่างตัวดำเนินการสเปรดและObject.assignที่ดูเหมือนจะไม่ได้กล่าวถึงในคำตอบปัจจุบันคือผู้ดำเนินการแพร่กระจายจะไม่คัดลอกต้นแบบของวัตถุต้นฉบับไปยังวัตถุเป้าหมาย Object.assignหากคุณต้องการที่จะเพิ่มคุณสมบัติวัตถุและคุณไม่ต้องการที่จะเปลี่ยนสิ่งที่มันเป็นตัวอย่างของแล้วคุณจะต้องใช้ ตัวอย่างด้านล่างควรแสดงสิ่งนี้:

const error = new Error();
error instanceof Error // true

const errorExtendedUsingSpread = {
  ...error,
  ...{
    someValue: true
  }
};
errorExtendedUsingSpread instanceof Error; // false

const errorExtendedUsingAssign = Object.assign(error, {
  someValue: true
});
errorExtendedUsingAssign instanceof Error; // true


"จะไม่เก็บต้นแบบไว้เหมือนเดิม" - แน่นอนเพราะจะไม่มีการแก้ไขอะไรเลย ในตัวอย่างของคุณerrorExtendedUsingAssign === errorแต่errorExtendedUsingSpreadเป็นวัตถุใหม่ (และต้นแบบไม่ได้ถูกคัดลอก)
maaartinus

2
@ maaartinus คุณพูดถูกฉันอาจพูดได้ไม่ดี ฉันหมายความว่าต้นแบบไม่ได้อยู่ในวัตถุที่คัดลอก ฉันอาจแก้ไขให้ชัดเจนยิ่งขึ้น
Sean Dawson

ต่อไปนี้เป็นวิธี "โคลนตื้น" วัตถุที่มีคลาสหรือไม่ let target = Object.create(source); Object.assign(target, source);
ToolmakerSteve

@ToolmakerSteve ใช่มันจะคัดลอก "คุณสมบัติของตัวเอง" ของวัตถุทั้งหมดซึ่งจะเป็นโคลนที่มีประสิทธิภาพ ดู: stackoverflow.com/questions/33692912/…
Sean Dawson

12

ดังที่คนอื่น ๆ ได้กล่าวไว้ในขณะนี้ในการเขียนObject.assign()ต้องใช้โปลิฟิลและการแพร่กระจายวัตถุ...ต้องมีการ transpiling (และอาจเป็นพอลิฟิลด้วย) เพื่อให้ทำงานได้

พิจารณารหัสนี้:

// Babel wont touch this really, it will simply fail if Object.assign() is not supported in browser.
const objAss = { message: 'Hello you!' };
const newObjAss = Object.assign(objAss, { dev: true });
console.log(newObjAss);

// Babel will transpile with use to a helper function that first attempts to use Object.assign() and then falls back.
const objSpread = { message: 'Hello you!' };
const newObjSpread = {...objSpread, dev: true };
console.log(newObjSpread);

ทั้งสองผลิตผลลัพธ์เดียวกัน

นี่คือผลลัพธ์จาก Babel ถึง ES5:

var objAss = { message: 'Hello you!' };
var newObjAss = Object.assign(objAss, { dev: true });
console.log(newObjAss);

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

var objSpread = { message: 'Hello you!' };
var newObjSpread = _extends({}, objSpread, { dev: true });
console.log(newObjSpread);

นี่คือความเข้าใจของฉันจนถึงตอนนี้ Object.assign()เป็นมาตรฐานจริงโดยที่การแพร่กระจายวัตถุ...ยังไม่เป็น ปัญหาเดียวคือการสนับสนุนเบราว์เซอร์สำหรับอดีตและในอนาคตหลังด้วย

เล่นกับรหัสที่นี่

หวังว่านี่จะช่วยได้


1
ขอบคุณ! ตัวอย่างโค้ดของคุณทำให้การตัดสินใจง่ายขึ้นสำหรับบริบทของฉัน transpiler (babel หรือ typescript) ทำให้ผู้ประกอบการแพร่กระจายเข้ากันได้กับเบราว์เซอร์มากขึ้นโดยรวม pollyfill ในรหัสแบบอินไลน์ เพียงเพื่อความสนใจ TypeScript transpiled เวอร์ชันก็เหมือนกับ Babel: typescriptlang.org/play/…
Mark Whitfeld

2
อืม ... ทั้งสองกรณีของคุณจะไม่ให้ผลลัพธ์เดียวกันหรือไม่ ในกรณีแรกคุณกำลังคัดลอกคุณสมบัติจากวัตถุหนึ่งไปยังอีกวัตถุหนึ่งและในอีกกรณีหนึ่งคุณกำลังสร้างวัตถุใหม่ Object.assign ส่งคืนเป้าหมายดังนั้นในกรณีแรกของคุณ objAss และ newObjAss เหมือนกัน
เควิน B

การเพิ่มพารามิเตอร์แรกใหม่ของ{}ควรแก้ไขความไม่สอดคล้องกัน
เควิน B

11

ตัวดำเนินการกระจายวัตถุ (... ) ไม่ทำงานในเบราว์เซอร์เนื่องจากยังไม่ได้เป็นส่วนหนึ่งของข้อกำหนด ES ใด ๆ เพียงข้อเสนอ ตัวเลือกเดียวคือรวบรวมด้วย Babel (หรือสิ่งที่คล้ายกัน)

อย่างที่คุณเห็นมันเป็นเพียงน้ำตาลซินแทคติคเหนือ Object.assign ({})

เท่าที่ฉันเห็นนี่เป็นความแตกต่างที่สำคัญ

  • Object.assign ทำงานในเบราว์เซอร์ส่วนใหญ่ (โดยไม่ต้องรวบรวม)
  • ... สำหรับวัตถุที่ไม่ได้มาตรฐาน
  • ... ปกป้องคุณจากการกลายพันธุ์วัตถุโดยไม่ตั้งใจ
  • ... จะ polyfill Object.assign ในเบราว์เซอร์โดยปราศจากมัน
  • ... ต้องการรหัสน้อยลงในการแสดงความคิดเดียวกัน

34
มันไม่ใช่น้ำตาลซินแทคติกเพราะObject.assignผู้ดำเนินการสเปรดจะให้วัตถุใหม่กับคุณเสมอ
MaxArt

4
ที่จริงแล้วฉันประหลาดใจที่คนอื่นไม่ได้เน้นความแตกต่างของความไม่แน่นอนมากขึ้น คิดถึงชั่วโมงของนักพัฒนาทั้งหมดที่สูญเสียการดีบักการกลายพันธุ์โดยไม่ตั้งใจด้วย Object.assign
deepelement

ตอนนี้ได้รับการสนับสนุนในเบราว์เซอร์ที่ทันสมัยที่สุด (เช่นเดียวกับ ES6 อื่น ๆ ): developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/
......

11

ฉันต้องการที่จะสรุปสถานะของฟีเจอร์ "spread object merge" ในเบราว์เซอร์และในระบบนิเวศผ่านเครื่องมือ

สเป็ค

เบราว์เซอร์: ใน Chrome, ใน SF, Firefox เร็ว ๆ นี้ (ver 60, IIUC)

  • การสนับสนุนเบราว์เซอร์สำหรับ "คุณสมบัติการแพร่กระจาย" จัดส่งใน Chrome 60รวมถึงสถานการณ์นี้
  • การสนับสนุนสำหรับสถานการณ์นี้ไม่ทำงานใน Firefox ปัจจุบัน (59) แต่ทำงานใน Firefox Developer Edition ของฉัน ดังนั้นฉันเชื่อว่ามันจะจัดส่งใน Firefox 60
  • Safari: ไม่ได้ทดสอบ แต่ Kangax บอกว่าใช้งานได้ใน Desktop Safari 11.1 แต่ไม่ใช่ SF 11
  • iOS Safari: ไม่ได้ทดสอบ แต่ Kangax บอกว่าใช้งานได้ใน iOS 11.3 แต่ไม่ใช่ใน iOS 11
  • ยังไม่ถึง Edge

เครื่องมือ: โหนด 8.7, TS 2.1

การเชื่อมโยง

ตัวอย่างโค้ด (เพิ่มเป็นสองเท่าเป็นการทดสอบความเข้ากันได้)

var x = { a: 1, b: 2 };
var y = { c: 3, d: 4, a: 5 };
var z = {...x, ...y};
console.log(z); // { a: 5, b: 2, c: 3, d: 4 }

อีกครั้ง: ในขณะที่เขียนตัวอย่างนี้จะทำงานโดยไม่มีการแปลงใน Chrome (60+), Firefox Developer Edition (ดูตัวอย่างของ Firefox 60) และ Node (8.7+)

ทำไมต้องตอบ

ฉันกำลังเขียนนี้ 2.5 ปีหลังจากคำถามเดิม แต่ฉันมีคำถามเดียวกันและนี่คือที่ Google ส่งมาให้ฉัน ฉันเป็นทาสของภารกิจของ SO เพื่อปรับปรุงหางยาว

เนื่องจากนี่เป็นการขยายตัวของ "อาร์เรย์การแพร่กระจาย" ฉันพบว่ามันยากมากที่ google และยากที่จะหาในตารางความเข้ากันได้ ที่ใกล้เคียงที่สุดที่ฉันจะหาได้คือKangax "property spread"แต่การทดสอบนั้นไม่มีการแพร่กระจายสองครั้งในนิพจน์เดียวกัน (ไม่ใช่การผสาน) นอกจากนี้ชื่อในหน้าสถานะข้อเสนอ / ฉบับร่าง / เบราว์เซอร์ทั้งหมดใช้ "คุณสมบัติการแพร่กระจาย" แต่ฉันก็ดูเหมือนว่าเป็น "หลักการแรก" ชุมชนมาถึงหลังจากข้อเสนอที่จะใช้ไวยากรณ์การแพร่กระจายสำหรับ "วัตถุผสาน" (ซึ่งอาจอธิบายได้ว่าทำไมมันจึงยากที่ google) ดังนั้นฉันบันทึกเอกสารการค้นหาของฉันที่นี่เพื่อให้ผู้อื่นสามารถดูอัปเดตและรวบรวมลิงก์เกี่ยวกับคุณลักษณะเฉพาะนี้ ฉันหวังว่ามันจะจับ กรุณาช่วยกระจายข่าวของมันเชื่อมโยงไปถึงใน spec และในเบราว์เซอร์

สุดท้ายฉันจะเพิ่มข้อมูลนี้เป็นความคิดเห็น แต่ฉันไม่สามารถแก้ไขได้โดยไม่ทำลายเจตนาดั้งเดิมของผู้เขียน โดยเฉพาะฉันไม่สามารถแก้ไขความคิดเห็นของ @ ChillyPenguin ได้หากไม่ได้ตั้งใจที่จะแก้ไข @RichardSchulte แต่หลายปีต่อมา Richard กลับกลายเป็นว่าถูก (ในความคิดของฉัน) ดังนั้นฉันจึงเขียนคำตอบนี้แทนหวังว่ามันจะได้คำตอบเดิม ๆ ในที่สุด (อาจต้องใช้เวลาหลายปี แต่นั่นคือสิ่งที่เอฟเฟ็กต์หางยาวนั้นเป็นอยู่


3
คุณอาจไม่จำเป็นต้องใช้ส่วน "ทำไมคำตอบ"
LocustHorde

@LocustHorde บางทีฉันสามารถย้ายย่อหน้าที่ 2 (ทำไมหัวข้อนี้ยากมากที่จะ google) ไปยังส่วนของตัวเอง จากนั้นส่วนที่เหลืออาจพอดีกับความคิดเห็น
yzorg

8

หมายเหตุ: การแพร่กระจายไม่ได้เป็นเพียงแค่วากยสัมพันธ์น้ำตาลรอบ Object.assign พวกเขาทำงานแตกต่างกันมากหลังฉาก

Object.assign ใช้ setters กับวัตถุใหม่ Spread ไม่ นอกจากนี้วัตถุจะต้องทำซ้ำได้

คัดลอก ใช้สิ่งนี้หากคุณต้องการคุณค่าของวัตถุในขณะนี้และคุณไม่ต้องการให้ค่านั้นสะท้อนการเปลี่ยนแปลงใด ๆ ที่เกิดขึ้นโดยเจ้าของวัตถุคนอื่น ๆ

ใช้สำหรับการสร้างสำเนาตื้นของแนวปฏิบัติที่ดีของวัตถุเพื่อตั้งค่าคุณสมบัติที่ไม่เปลี่ยนรูปแบบให้คัดลอกเสมอ - เนื่องจากเวอร์ชันที่เปลี่ยนแปลงไม่ได้สามารถส่งผ่านไปยังคุณสมบัติที่ไม่เปลี่ยนรูปแบบได้คัดลอกจะทำให้แน่ใจว่าคุณจะจัดการกับวัตถุที่ไม่เปลี่ยนรูป

Assign Assign ค่อนข้างตรงกันข้ามกับการคัดลอก Assign จะสร้าง setter ที่กำหนดค่าให้กับตัวแปรอินสแตนซ์โดยตรงแทนที่จะคัดลอกหรือเก็บรักษาไว้ เมื่อเรียก getter ของคุณสมบัติ assign มันจะส่งคืนการอ้างอิงไปยังข้อมูลจริง


3
ทำไมถึงพูดว่า "Copy" ส่วนหัวที่หนาเหล่านี้คืออะไร ฉันรู้สึกเหมือนฉันพลาดบางบริบทเมื่อฉันอ่านนี้ ...
ADJenks

2

คำตอบอื่น ๆ เก่าไม่สามารถรับคำตอบที่ดี
ตัวอย่างด้านล่างสำหรับตัวอักษรวัตถุช่วยให้ทั้งสองสามารถเติมเต็มซึ่งกันและกันและวิธีที่ไม่สามารถเติมเต็มซึ่งกันและกัน (ดังนั้นจึงแตกต่างกัน):

var obj1 = { a: 1,  b: { b1: 1, b2: 'b2value', b3: 'b3value' } };

// overwrite parts of b key
var obj2 = {
      b: {
        ...obj1.b,
        b1: 2
      }
};
var res2 = Object.assign({}, obj1, obj2); // b2,b3 keys still exist
document.write('res2: ', JSON.stringify (res2), '<br>');
// Output:
// res2: {"a":1,"b":{"b1":2,"b2":"b2value","b3":"b3value"}}  // NOTE: b2,b3 still exists

// overwrite whole of b key
var obj3 = {
      b: {
        b1: 2
      }
};
var res3 = Object.assign({}, obj1, obj3); // b2,b3 keys are lost
document.write('res3: ', JSON.stringify (res3), '<br>');
// Output:
  // res3: {"a":1,"b":{"b1":2}}  // NOTE: b2,b3 values are lost

ตัวอย่างเล็ก ๆ น้อย ๆ เพิ่มเติมที่นี่เช่นกันสำหรับอาร์เรย์และวัตถุ:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax


1

ตอนนี้เป็นส่วนหนึ่งของ ES6 ดังนั้นจึงเป็นมาตรฐานและได้รับการบันทึกไว้ใน MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator

สะดวกในการใช้งานและใช้งานได้อย่างเหมาะสมควบคู่กับการทำลายวัตถุ

ข้อได้เปรียบที่เหลืออีกข้อหนึ่งที่ระบุไว้ด้านบนคือความสามารถแบบไดนามิกของ Object.assign () แต่นี่เป็นเรื่องง่ายเหมือนกับการกระจายอาเรย์ภายในวัตถุตัวอักษร ในผลลัพธ์ Babel ที่รวบรวมจะใช้สิ่งที่แสดงให้เห็นด้วย Object.assign ()

ดังนั้นคำตอบที่ถูกต้องคือการใช้การแพร่กระจายของวัตถุเนื่องจากตอนนี้เป็นมาตรฐานใช้กันอย่างแพร่หลาย (ดูการตอบสนอง, การเปลี่ยนสี, ฯลฯ ) ใช้งานง่ายและมีคุณสมบัติทั้งหมดของ Object.assign ()


2
ไม่มันไม่ใช่ส่วนหนึ่งของ ES6 ลิงก์ที่คุณให้มาหมายถึงการใช้โอเปอเรเตอร์ของอาร์เรย์เท่านั้น การใช้ตัวดำเนินการสเปรดบนวัตถุในปัจจุบันเป็นข้อเสนอ Stage 2 (เช่นร่าง) ดังที่อธิบายไว้ในคำตอบของ JMM
ChillyPenguin

1
ฉันไม่คิดว่าฉันเคยเห็นคำตอบทั้งหมดมาจากข้อมูลเท็จทั้งหมด แม้แต่หนึ่งปีต่อมานั่นไม่ได้เป็นส่วนหนึ่งหากข้อมูลจำเพาะ ES และไม่รองรับในสภาพแวดล้อมส่วนใหญ่
3ocene

Chilly กับ 3o กลับกลายเป็นว่าผิดริชาร์ดพูดถูก การสนับสนุนเบราว์เซอร์และการสนับสนุนเครื่องมือนั้นเชื่อมโยงไปถึงทั้งหมด แต่ใช้เวลา 1.5 ปีหลังจากคำตอบของ Richard ดูคำตอบใหม่ของฉันสำหรับการสรุปการสนับสนุนตั้งแต่มีนาคม 2018
yzorg

0

ฉันต้องการเพิ่มตัวอย่างง่ายๆนี้เมื่อคุณต้องใช้ Object.assign

class SomeClass {
  constructor() {
    this.someValue = 'some value';
  }

  someMethod() {
    console.log('some action');
  }
}


const objectAssign = Object.assign(new SomeClass(), {});
objectAssign.someValue; // ok
objectAssign.someMethod(); // ok

const spread = {...new SomeClass()};
spread.someValue; // ok
spread.someMethod(); // there is no methods of SomeClass!

อาจไม่ชัดเจนเมื่อคุณใช้ JavaScript แต่ด้วย TypeScript จะง่ายกว่าถ้าคุณต้องการสร้างอินสแตนซ์ของคลาสบางคลาส

const spread: SomeClass = {...new SomeClass()} // Error
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.