จุดสามจุดในการตอบสนองทำอะไร


897

สิ่งที่...ต้องทำในโค้ดของ React (ใช้ JSX) และเรียกว่าอะไร?

<Modal {...this.props} title='Modal heading' animation={false}>

6
Theres เป็นการอ่านที่ง่ายและเข้าใจได้ที่นี่ในไวยากรณ์การแพร่กระจาย - codeburst.io/javascript-es6-the-spread-syntax-f5c35525f754
Gautam

5
หมายเหตุ: ...ผู้ปฏิบัติงานจะทำงานแตกต่างกันในบริบทที่แตกต่างกัน ในบริบทนี้เป็นตัวดำเนินการ "spread" ที่อธิบายด้านล่างโดย @TJ Crowder ในบริบทอื่นอาจเป็นตัวดำเนินการ "พักผ่อน" ที่อธิบายไว้ด้านล่างโดย @Tomas Nikodym
doub1ejack

คำตอบ:


1064

นั่นเป็นสัญกรณ์การแพร่กระจายทรัพย์สิน มันถูกเพิ่มเข้ามาใน ES2018 (สเปรดสำหรับอาร์เรย์ / iterables เป็นรุ่นก่อนหน้านี้ ES2015) แต่ได้รับการสนับสนุนในโครงการ React เป็นเวลานานผ่านการถ่ายโอน (ในฐานะ " JSX spread attributes " แม้ว่าคุณจะสามารถทำได้ที่อื่นเช่นกัน )

{...this.props} กระจายคุณสมบัติที่นับได้ "ของตัวเอง" ออกมาเป็นคุณสมบัติpropsที่ไม่ต่อเนื่องของModalองค์ประกอบที่คุณกำลังสร้าง ตัวอย่างเช่นหากthis.propsมีa: 1และb: 2จากนั้น

<Modal {...this.props} title='Modal heading' animation={false}>

จะเป็นเช่นเดียวกับ

<Modal a={this.props.a} b={this.props.b} title='Modal heading' animation={false}>

แต่มันเป็นแบบไดนามิกดังนั้นสิ่งที่คุณสมบัติ "ของตัวเอง" propsจะรวมอยู่ใน

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

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

this.setState(prevState => {
    return {foo: {...prevState.foo, a: "updated"}};
});

ที่แทนที่this.state.fooด้วยวัตถุใหม่ที่มีคุณสมบัติเดียวกันfooทั้งหมดยกเว้นaทรัพย์สินซึ่งกลายเป็น"updated":


1
ไม่วางองค์ประกอบลูกระหว่างการเปิดและปิดแท็กแทนที่childrenทรัพย์สินหรือที่พวกเขาทำงานร่วมกัน?
anddero

3
@anddero - นั่นเป็นคำถามที่น่าสนใจมาก เท่าที่ผมสามารถมองเห็นก็ไม่ได้ครอบคลุมโดย [เอกสารchildrenของ การทดลองบอกเด็ก ๆ ที่คุณให้ผ่านแอททริบิวที่เรียกว่าchildrenถูกแทนที่ด้วยแท็กที่คุณระบุระหว่างแท็กเริ่มต้นและแท็กสิ้นสุด แต่ถ้ามันเป็นพฤติกรรมที่ไม่ได้กำหนดฉันจะต้องไม่พึ่งพามัน
TJ Crowder

332

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

var parts = ['two', 'three'];
var numbers = ['one', ...parts, 'four', 'five']; // ["one", "two", "three", "four", "five"]

และในกรณีนี้ (ฉันจะทำให้มันง่ายขึ้น)

//just assume we have an object like this:
var person= {
    name: 'Alex',
    age: 35 
}

นี้:

<Modal {...person} title='Modal heading' animation={false} />

เท่ากับ

<Modal name={person.name} age={person.age} title='Modal heading' animation={false} />

ดังนั้นในระยะสั้นมันเป็นทางลัดที่เรียบร้อยเราสามารถพูดได้


155

จุดสามจุดแสดงถึงตัวดำเนินการสเปรดใน ES6 ช่วยให้เราสามารถทำบางสิ่งใน Javascript:

  1. เชื่อมต่ออาร์เรย์

    var shooterGames = ['Call of Duty', 'Far Cry', 'Resident Evil'];
    var racingGames = ['Need For Speed', 'Gran Turismo', 'Burnout'];
    var games = [...shooterGames, ...racingGames];
    
    console.log(games)  // ['Call of Duty', 'Far Cry', 'Resident Evil',  'Need For Speed', 'Gran Turismo', 'Burnout']
  2. การทำลายอาร์เรย์

      var shooterGames = ['Call of Duty', 'Far Cry', 'Resident Evil'];
      var [first, ...remaining] = shooterGames;
      console.log(first); //Call of Duty
      console.log(remaining); //['Far Cry', 'Resident Evil']
  3. รวมสองวัตถุ

    var myCrush = {
      firstname: 'Selena',
      middlename: 'Marie'
    };
    
    var lastname = 'my last name';
    
    var myWife = {
      ...myCrush,
      lastname
    }
    
    console.log(myWife); // {firstname: 'Selena',
                         //   middlename: 'Marie',
                         //   lastname: 'my last name'}

มีการใช้งานอีกสามจุดซึ่งเรียกว่าRest Parametersและทำให้สามารถนำอาร์กิวเมนต์ทั้งหมดไปใช้กับฟังก์ชันเป็นอาร์เรย์เดียวได้

  1. ฟังก์ชันอาร์กิวเมนต์เป็นอาร์เรย์

     function fun1(...params) { 
    
     }  

36
นี่คือคำตอบที่ดีเพราะตัวอย่างที่ชัดเจนสำหรับการใช้งานแต่ละกรณี ขอบคุณที่สละเวลาเขียนทั้งหมดนี้
ชาด

2
พูดถึงพารามิเตอร์ที่เหลือต่อหน้าตัวอย่างเพื่อความชัดเจนมากขึ้น
j obe

2
upvoted นี่คือสิ่งที่ฉันกำลังมองหา
Csaba

2
สุจริตนี่ควรเป็นคำตอบที่ยอมรับ +1
I_am_learning_now

1
ไม่เพียง แต่คำตอบที่ดีที่สุดยังเป็นคำที่ตลกที่สุด 'เซลาน่ามารีปิ๊งคนแรกของคุณ: D'
Andaç Temel

56

ทั้งสามจุดใน JavaScript มีการแพร่กระจาย / ผู้ประกอบการส่วนที่เหลือ

ผู้ประกอบการแพร่กระจาย

ไวยากรณ์การแพร่กระจายช่วยให้การแสดงออกที่จะขยายตัวในสถานที่ที่มีปากเสียงหลายที่คาดว่า

myFunction(...iterableObj);

[...iterableObj, 4, 5, 6]

[...Array(10)]

พารามิเตอร์ที่เหลือ

เหลือไวยากรณ์พารามิเตอร์ที่ใช้สำหรับฟังก์ชั่นที่มีจำนวนตัวแปรของการขัดแย้ง

function(a, b, ...theArgs) {
  // ...
}

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

typescript ยังสนับสนุนไวยากรณ์การแพร่กระจายและสามารถ transpile ที่เป็นรุ่นเก่าของ ECMAScript กับผู้เยาว์ปัญหา


สเปรด / พักผ่อนตอนนี้เป็นสเตจ 4 เสร็จสิ้นแล้ว ฉันคิดว่ารวมอยู่ใน ES9 / 2018 github.com/tc39/proposal-object-rest-spread/blob/master/ …
SeanMC

32

นี่คือคุณสมบัติของ ES6 ซึ่งใช้ในการตอบสนองเช่นกัน ดูตัวอย่างด้านล่าง:

function Sum(x,y,z) {
   return x + y + z;
}
console.log(Sum(1,2,3)); //6

วิธีนี้ใช้ได้ถ้าเรามีพารามิเตอร์สูงสุด 3 ตัว แต่ถ้าเราต้องการเพิ่มเช่น 110 พารามิเตอร์ เราควรนิยามพวกมันทั้งหมดและเพิ่มพวกมันทีละตัว?

แน่นอนมีวิธีที่ง่ายต่อการทำซึ่งเรียกว่าSPREAD แทนที่จะเขียนพารามิเตอร์ทั้งหมดที่คุณเขียน:

function (...numbers){} 

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

let Sum = (...numbers) => {
return numbers.reduce((prev, current) => prev + current );
}
console.log(Sum(1, 2, 3, 4, 5, 6, 7, 8, 9));//45

17

มันเป็นเพียงการกำหนดอุปกรณ์ประกอบฉากในวิธีที่แตกต่างในJSXสำหรับคุณ!

มันใช้...ตัวดำเนินการอาร์เรย์และวัตถุใน ES6 (วัตถุที่ยังไม่รองรับอย่างสมบูรณ์) ดังนั้นโดยทั่วไปถ้าคุณกำหนดอุปกรณ์ประกอบฉากของคุณแล้วคุณสามารถส่งมันไปยังองค์ประกอบของคุณได้ด้วยวิธีนี้

ดังนั้นในกรณีของคุณรหัสควรเป็นดังนี้:

function yourA() {
  const props = {name='Alireza', age='35'};
  <Modal {...props} title='Modal heading' animation={false} />
}

ดังนั้นอุปกรณ์ประกอบฉากที่คุณกำหนดแยกตอนนี้และสามารถนำกลับมาใช้ใหม่ได้หากจำเป็น

มันเท่ากับ:

function yourA() {
  <Modal name='Alireza' age='35' title='Modal heading' animation={false} />
}

นี่คือคำพูดจากทีมตอบโต้เกี่ยวกับผู้ดำเนินการสเปรดใน JSX:

คุณสมบัติการกระจาย JSX หากคุณรู้คุณสมบัติทั้งหมดที่คุณต้องการวางไว้บนองค์ประกอบก่อนเวลามันง่ายต่อการใช้ JSX:

var component = <Component foo={x} bar={y} />;

การกลายพันธุ์อุปกรณ์ประกอบฉากไม่ดี
หากคุณไม่ทราบว่าคุณสมบัติใดที่คุณต้องการตั้งค่าคุณอาจถูกล่อลวงให้เพิ่มมันลงในวัตถุในภายหลัง:

var component = <Component />;
component.props.foo = x; // bad
component.props.bar = y; // also bad

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

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

คุณสมบัติการแพร่กระจาย
ตอนนี้คุณสามารถใช้คุณสมบัติใหม่ของ JSX ที่เรียกว่าคุณลักษณะการแพร่กระจาย:

var props = {};
    props.foo = x;
    props.bar = y;
    var component = <Component {...props} />;

คุณสมบัติของวัตถุที่คุณส่งผ่านถูกคัดลอกไปยังอุปกรณ์ประกอบฉากของส่วนประกอบ

คุณสามารถใช้หลาย ๆ ครั้งหรือรวมเข้ากับคุณสมบัติอื่น ๆ ลำดับข้อกำหนดมีความสำคัญ คุณลักษณะในภายหลังจะแทนที่รายการก่อนหน้า

var props = { foo: 'default' };
var component = <Component {...props} foo={'override'} />;
console.log(component.props.foo); // 'override'

สัญกรณ์อะไรแปลก ๆ ...
ตัวดำเนินการ ... (หรือตัวดำเนินการแพร่กระจาย) ได้รับการสนับสนุนสำหรับอาร์เรย์ใน ES6 แล้ว นอกจากนี้ยังมีข้อเสนอ ECMAScript สำหรับวัตถุที่เหลือและคุณสมบัติการแพร่กระจาย เราใช้ประโยชน์จากมาตรฐานที่ได้รับการสนับสนุนและพัฒนาเหล่านี้เพื่อให้ไวยากรณ์ที่สะอาดยิ่งขึ้นใน JSX


15

สำหรับผู้ที่มาจากโลก Python คุณสมบัติ JSX Spread เทียบเท่ากับ การคลายรายการอาร์กิวเมนต์ (Python **-operator)

ฉันรู้ว่านี่เป็นคำถาม JSX แต่การทำงานกับการเปรียบเทียบบางครั้งช่วยในการทำให้เร็วขึ้น


10

...(ผู้ประกอบการแพร่) จะใช้ในการตอบสนองต่อ:

จัดหาวิธีการที่เป็นระเบียบในการส่งอุปกรณ์จากผู้ปกครองไปยังส่วนประกอบของเด็ก เช่นได้รับอุปกรณ์ประกอบฉากเหล่านี้ในองค์ประกอบหลัก

this.props = {
  username: "danM",
  email: "dan@mail.com"
}

พวกเขาสามารถส่งต่อไปยังเด็ก

<ChildComponent {...this.props} />

ซึ่งคล้ายกับสิ่งนี้

<ChildComponent username={this.props.username} email={this.props.email} />

แต่วิธีทำความสะอาด


9

จุดสามจุด...หมายถึงผู้ประกอบการแพร่กระจายหรือส่วนที่เหลือพารามิเตอร์ ,

จะช่วยให้การแสดงออกอาร์เรย์หรือสตริงหรืออะไรก็ได้ที่สามารถทำซ้ำที่จะขยายในสถานที่คาดว่าศูนย์หรือมากกว่าอาร์กิวเมนต์สำหรับการเรียกใช้ฟังก์ชั่นหรือองค์ประกอบสำหรับอาร์เรย์ที่คาดว่า

  • ผสานสองอาร์เรย์

var arr1 = [1,2,3];
var arr2 = [4,5,6];

arr1 = [...arr1, ...arr2];
console.log(arr1);  //[1, 2, 3, 4, 5, 6]

  • คัดลอกอาร์เรย์:

var arr = [1, 2, 3];
var arr2 = [...arr];

console.log(arr); //[1, 2, 3]

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

  • เพิ่มค่าของอาร์เรย์หนึ่งไปยังอีกแถวที่ดัชนีเฉพาะเช่น 3:

var arr1 = [4,5]
var arr2 = [1,2,3,...arr1,6]
console.log(arr2);	// [1, 2, 3, 4, 5, 6]

  • เมื่อเรียกนวกรรมิกด้วยตัวใหม่:

var dateFields = [1970, 0, 1];  // 1 Jan 1970
var d = new Date(...dateFields);

console.log(d);

  • การแพร่กระจายในวัตถุตัวอักษร:

var obj1 = { foo: 'bar', x: 42 };
var obj2 = { foo: 'baz', y: 13 };

var clonedObj = { ...obj1 };
console.log(clonedObj);	//{foo: "bar", x: 42}

var mergedObj = { ...obj1, ...obj2 };
console.log(mergedObj);	//{foo: "baz", x: 42, y: 13}

โปรดสังเกตว่าfooคุณสมบัติของ obj1 ถูกเขียนทับโดยfooคุณสมบัติobj2

  • ในฐานะที่เป็นไวยากรณ์ส่วนที่เหลือพารามิเตอร์ซึ่งช่วยให้เราสามารถแสดงจำนวนอาร์กิวเมนต์ไม่ จำกัด เป็นอาร์เรย์:

function sum(...theArgs) {
  return theArgs.reduce((previous, current) => {
    return previous + current;
  });
}

console.log(sum(1, 2, 3));	//6
console.log(sum(1, 2, 3, 4));	//10

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

var obj = {'key1': 'value1'};
var array = [...obj]; // TypeError: obj is not iterable

Reference1

Reference2


5

รุ่งโรจน์ถึงแบรนดอนมอเรลลี เขาอธิบายอย่างสมบูรณ์แบบที่นี่แต่ลิงก์อาจตายดังนั้นฉันจึงวางเนื้อหาด้านล่างนี้:

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

ตัวอย่าง # 1 - การแทรกอาร์เรย์ ลองดูรหัสด้านล่าง ในรหัสนี้เราจะไม่ใช้ไวยากรณ์การแพร่กระจาย:

var mid = [3, 4];
var arr = [1, 2, mid, 5, 6];

console.log(arr);

midดังกล่าวข้างต้นเราได้สร้างอาร์เรย์ชื่อ จากนั้นเราจะสร้างอาร์เรย์ที่สองซึ่งมีmidอาร์เรย์ของเรา ในที่สุดเราออกจากระบบผลลัพธ์ คุณคาดว่าarrจะพิมพ์อะไร คลิกเรียกใช้ด้านบนเพื่อดูว่าเกิดอะไรขึ้น นี่คือผลลัพธ์:

[1, 2, [3, 4], 5, 6]

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

var mid = [3, 4];
var arr = [1, 2, ...mid, 5, 6];

console.log(arr);

และเมื่อคุณกดปุ่ม run นี่คือผลลัพธ์:

[1, 2, 3, 4, 5, 6]

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

ตัวอย่าง # 2 - Math JavaScript มีวัตถุทางคณิตศาสตร์ในตัวที่ช่วยให้เราทำการคำนวณทางคณิตศาสตร์ที่สนุกสนาน Math.max()ในตัวอย่างนี้เราจะมองไปที่ หากคุณไม่คุ้นเคยให้Math.max()ส่งกลับตัวเลขที่มากที่สุดของศูนย์หรือมากกว่า นี่คือตัวอย่างบางส่วน:

Math.max();
// -Infinity
Math.max(1, 2, 3);
// 3
Math.max(100, 3, 4);
// 100

อย่างที่คุณเห็นหากคุณต้องการหาค่าสูงสุดของตัวเลขหลายตัวMath.max()ต้องใช้พารามิเตอร์หลายตัว น่าเสียดายที่คุณไม่สามารถใช้อาร์เรย์เดียวเป็นอินพุตได้ ก่อนไวยากรณ์การแพร่กระจายวิธีที่ง่ายที่สุดที่จะใช้Math.max()ในอาเรย์คือการใช้.apply()

var arr = [2, 4, 8, 6, 0];

function max(arr) {
  return Math.max.apply(null, arr);
}

console.log(max(arr));

มันใช้งานได้มันน่ารำคาญจริงๆ ตอนนี้มาดูกันว่าเราทำสิ่งเดียวกันกับไวยากรณ์การกระจาย:

var arr = [2, 4, 8, 6, 0];
var max = Math.max(...arr);

console.log(max);

แทนที่จะต้องสร้างฟังก์ชั่นและใช้วิธีการใช้เพื่อคืนผลลัพธ์Math.max()เราต้องใช้โค้ดสองบรรทัด! ไวยากรณ์การแพร่กระจายขยายองค์ประกอบอาร์เรย์ของเราและใส่แต่ละองค์ประกอบในอาร์เรย์ของเราเป็นรายบุคคลลงในMath.max()วิธีการ!

ตัวอย่าง # 3 - คัดลอกอาร์เรย์ ใน JavaScript คุณไม่สามารถเพียงแค่คัดลอกอาร์เรย์โดยการตั้งค่าตัวแปรใหม่ให้เท่ากับอาร์เรย์ที่มีอยู่แล้ว พิจารณาตัวอย่างรหัสต่อไปนี้:

var arr = ['a', 'b', 'c'];
var arr2 = arr;

console.log(arr2);

เมื่อคุณกดเรียกใช้คุณจะได้ผลลัพธ์ต่อไปนี้:

['a', 'b', 'c']

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

var arr = ['a', 'b', 'c'];
var arr2 = arr;

arr2.push('d');

console.log(arr);

ด้านบนเราได้ผลักองค์ประกอบใหม่ลงใน arr2 แต่เมื่อเราออกจากระบบค่า arr คุณจะเห็นว่าค่า d ถูกเพิ่มไปยังอาร์เรย์นั้นด้วย:

['a', 'b', 'c', 'd']

ไม่จำเป็นต้องกลัวว่า! เราสามารถใช้ผู้ดำเนินการแพร่กระจาย! พิจารณารหัสด้านล่าง มันเกือบจะเหมือนกับข้างต้น แต่เราได้ใช้ตัวดำเนินการสเปรดภายในวงเล็บเหลี่ยมสองอัน:

var arr = ['a', 'b', 'c'];
var arr2 = [...arr];

console.log(arr2);

กดรันแล้วคุณจะเห็นผลลัพธ์ที่คาดหวัง:

['a', 'b', 'c']

ด้านบนค่าอาร์เรย์ใน arr ขยายเป็นองค์ประกอบแต่ละอันซึ่งถูกกำหนดให้กับ arr2 แล้ว ตอนนี้เราสามารถเปลี่ยนอาร์เรย์ arr2 ได้มากเท่าที่เราต้องการโดยไม่มีผลกระทบต่ออาร์เรย์ arr2 เดิม:

var arr = ['a', 'b', 'c'];
var arr2 = [...arr];

arr2.push('d');

console.log(arr);

อีกครั้งเหตุผลที่การทำงานนี้เป็นเพราะค่าของ arr ถูกขยายเพื่อเติมวงเล็บของนิยามอาร์เรย์ของเรา arr2 ดังนั้นเรากำลังตั้งค่า arr2 ให้เท่ากับค่าแต่ละค่าของ arr แทนการอ้างอิงถึง arr เหมือนที่เราทำในตัวอย่างแรก

ตัวอย่างโบนัส - String to Array เป็นตัวอย่างสุดท้ายที่สนุกคุณสามารถใช้ไวยากรณ์การแพร่กระจายเพื่อแปลงสตริงเป็นอาร์เรย์ เพียงใช้ไวยากรณ์การแพร่กระจายภายในวงเล็บเหลี่ยมสองอัน:

var str = "hello";
var chars = [...str];

console.log(chars);


4

จุดสามจุด(...)นี้เรียกว่าตัวดำเนินการแพร่กระจายและนี่คือแนวคิดคล้ายกับตัวดำเนินการแพร่กระจายอาร์เรย์ ES6, JSX ใช้ประโยชน์จากมาตรฐานที่ได้รับการสนับสนุนและพัฒนาเหล่านี้เพื่อให้ไวยากรณ์ที่สะอาดยิ่งขึ้นใน JSX

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

let n = { x, y, ...z };
n; // { x: 1, y: 2, a: 3, b: 4 }

อ้างอิง:

1) https://github.com/sebmarkbage/ecmascript-rest-spread#spread-properties

2) https://facebook.github.io/react/docs/jsx-spread.html


3
นั่นเป็นข้อเสนอสำหรับโอเปอเรเตอร์การแพร่กระจายบนวัตถุใน ECMAScript คำถามเกี่ยวกับตัวดำเนินการแพร่กระจาย JSX พวกเขาไม่เหมือนกันแม้ว่าพวกเขาจะทำงานในลักษณะเดียวกัน
ivarni

1
@ivarni ขอบคุณที่นำฉันเข้าสู่บริบทให้เวลาฉันสักครู่จะอัปเดตคำตอบตามบริบทของคำถาม
นักพัฒนา

@ivarni อัปเดตคำตอบตามบริบทหวังว่าสิ่งนี้เหมาะสมกับบริบท
นักพัฒนา

"จุดสามจุด (... ) เรียกว่าตัวดำเนินการแพร่กระจาย"ไม่ถูกต้องเท่านั้น :-) การแพร่กระจายและการพักไม่ใช่ตัวดำเนินการและไม่สามารถทำได้เนื่องจากผู้ดำเนินการต้องสร้างผลลัพธ์ผลลัพธ์เดียว สเปรดและส่วนที่เหลือเป็นไวยากรณ์หลักไม่ใช่ตัวดำเนินการ
TJ Crowder

2

ความหมายของ ... ขึ้นอยู่กับตำแหน่งที่คุณใช้ในรหัส

  1. ใช้สำหรับการแพร่กระจาย / คัดลอกอาร์เรย์ / วัตถุ - ช่วยในการคัดลอกอาร์เรย์ / วัตถุและยังเพิ่มค่าอาร์เรย์ใหม่ / เพิ่มคุณสมบัติใหม่ให้กับวัตถุซึ่งเป็นตัวเลือก

const numbers = [1,2,3];
const newNumbers = [...numbers, 4];
console.log(newNumbers) //prints [1,2,3,4] 

const person = {
 name: 'Max'
};

const newPerson = {...person, age:28};
console.log(newPerson); //prints {name:'Max', age:28}

  1. ใช้สำหรับการรวมอาร์กิวเมนต์ของฟังก์ชันลงในอาร์เรย์เดียว - จากนั้นคุณสามารถใช้ฟังก์ชันอาร์เรย์ในนั้นได้

const filter = (...args) => {
   return args.filter(el => el ===1);
}

console.log(filter(1,2,3)); //prints [1] 


2

นี่คือผู้ประกอบการแพร่กระจาย ...

ตัวอย่างเช่นถ้าคุณมีอาร์เรย์และอื่น ๆfirst=[1,2,3,4,5]second=[6,7,8]

[...first, ...second] //result is [1,2,3,4,5,6,7,8]

เดียวกันสามารถทำได้กับวัตถุ json


2

ในระยะสั้นจุดสามจุด...เป็นผู้ดำเนินการแพร่กระจายใน ES6 (ES2015) ผู้ประกอบการแพร่กระจายจะดึงข้อมูลทั้งหมด

let a = [1, 2, 3, 4];
let b = [...a, 4, 5, 6];
let c = [7,8,...a];


console.log(b);

จะให้ผลลัพธ์ [1,2,3,4,5,6]

console.log(c);

จะให้ผลลัพธ์ [7,8,1,2,3,4]


1

มักเรียกว่าสเปรดโอเปอเรเตอร์มันถูกใช้เพื่อขยายตามที่ต้องการ

ตัวอย่าง

const SomeStyle = {
   margin:10,
   background:#somehexa
}

คุณสามารถใช้ที่เคยคุณต้องใช้มันมากขึ้นเกี่ยวกับการแพร่กระจายประกอบไวยากรณ์การแพร่กระจาย


1

คุณสมบัติการแพร่กระจายที่ใช้ในการผ่านคุณสมบัติหลายอย่างในวิธีที่ง่าย

{... this.props} กำลังถือครองทรัพย์สินของ this.props

การใช้ตัวดำเนินการกระจาย ... {... } พร้อมอุปกรณ์ประกอบฉากด้านล่าง

this.props = 
 { 
    firstName: 'Dan', 
    lastName: 'Abramov', 
    city: 'New York',
    country: 'USA' 
}

โดยไม่มี {... } สเปรด

<Child 
  firstName={this.props.firstName}
  lastName={this.props.lastName}
  city={this.props.city}
  country={this.props.country}

> 

ด้วย {... } สเปรด

<Child { ...this.props } />

ทวีตของ Dan Abramovเกี่ยวกับโอเปอเรเตอร์ Spread (ผู้สร้าง Redux)


1

... ไวยากรณ์นี้เป็นส่วนหนึ่งของ ES6 และไม่ใช่สิ่งที่คุณสามารถใช้ใน React เท่านั้นมันสามารถใช้งานได้สองวิธี ในฐานะผู้ดำเนินการสเปรดหรือเป็นพารามิเตอร์ส่วนที่เหลือคุณสามารถค้นหาเพิ่มเติมได้จากบทความนี้: https://www.techiediaries.com/react-spread-operator-props-setstate/

สิ่งที่คุณพูดถึงในคำถามคืออะไรอย่างนี้สมมุติว่าเป็นแบบนี้

    function HelloUser() {
      return <Hello Name="ABC" City="XYZ" />;
    }

ด้วยการใช้ตัวดำเนินการสเปรดคุณสามารถส่งอุปกรณ์ประกอบฉากไปยังส่วนประกอบเช่นนี้

     function HelloUser() {
       const props = {Name: 'ABC', City: 'XYZ'};
       return <Hello {...props} />;
     }

0

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

กระบวนการทั่วไปของการส่งอุปกรณ์ประกอบฉากไปยังเด็กนั้นถูกบันทึกไว้ด้วยไวยากรณ์นี้:

var component = <Component foo={x} bar={y} />;

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

var component = <Component />;
component.props.foo = x; // bad
component.props.bar = y;

ผลลัพธ์เดียวกันนี้สามารถทำได้ แต่มีความสำเร็จที่เหมาะสมมากขึ้นโดยทำสิ่งนี้:

var props = {};
props.foo = x;
props.bar = y;
var component = Component(props); // Where did my JSX go?

แต่ไม่ได้ใช้การแพร่กระจาย JSX หรือ JSX เพื่อวนกลับเข้าไปในสมการตอนนี้เราสามารถทำสิ่งนี้:

var props = {};
props.foo = x;
props.bar = y;
var component = <Component {...props} />;

คุณสมบัติที่รวมอยู่ใน "... props" คือ foo: x, bar: y สิ่งนี้สามารถใช้ร่วมกับคุณสมบัติอื่น ๆ เพื่อแทนที่คุณสมบัติของ "... props" โดยใช้ไวยากรณ์นี้:

var props = { foo: 'default' };
var component = <Component {...props} foo={'override'} />;
console.log(component.props.foo); // 'override'

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

var oldObj = { foo: 'hello', bar: 'world' };
var newObj = { ...oldObj, foo: 'hi' };
console.log(newObj.foo); // 'hi';
console.log(newObj.bar); // 'world';

หรือรวมสองวัตถุที่แตกต่างเช่นนี้ (ยังไม่พร้อมใช้งานในรุ่นตอบกลับทั้งหมด):

var ab = { ...a, ...b }; // merge(a, b)

อีกวิธีในการอธิบายสิ่งนี้ตามไซต์การตอบสนอง / เอกสารของ Facebook คือ:

หากคุณมี "อุปกรณ์ประกอบฉาก" เป็นวัตถุอยู่แล้วและคุณต้องการส่งต่อใน JSX คุณสามารถใช้ "... " เป็นผู้ประกอบการ SPREAD เพื่อส่งผ่านวัตถุอุปกรณ์ประกอบฉากทั้งหมด ตัวอย่างสองตัวอย่างต่อไปนี้เทียบเท่า:

function App1() {
  return <Greeting firstName="Ben" lastName="Hector" />;
}



function App2() {
  const props = {firstName: 'Ben', lastName: 'Hector'};
  return <Greeting {...props} />;
}

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


0

มันเรียกว่าผู้ประกอบการแพร่กระจาย ตัวอย่างเช่น let hello = {name: '', msg: ''} let hello1 = {... hello} ตอนนี้คุณสมบัติของวัตถุ hello จะถูกคัดลอกไปที่ hello1


0

มันเรียกว่าการกระจายไวยากรณ์ในจาวาสคริปต์

มันใช้สำหรับการทำลายอาร์เรย์หรือวัตถุในจาวาสคริปต์

ตัวอย่าง:

const objA = { a: 1, b: 2, c: 3 }
const objB = { ...objA, d: 1 }
/* result of objB will be { a: 1, b: 2, c: 3, d: 1 } */
console.log(objB)

const objC = { ....objA, a: 3 }
/* result of objC will be { a: 3, b: 2, c: 3, d: 1 } */
console.log(objC)

คุณสามารถทำมันผลลัพธ์เดียวกันกับObject.assign()ฟังก์ชันใน javascript

การอ้างอิง: ไวยากรณ์สเปรด


0

สิ่งนี้จะถูกรวบรวมเป็น:

React.createElement(Modal, { ...this.props, title: "Modal heading", animation: false }, child0, child1, child2, ...)

โดยที่มันให้คุณสมบัติมากกว่าสองอย่างtitle& animationนอกเหนือจากpropsองค์ประกอบโฮสต์มี

...คือโอเปอเรเตอร์ ES6 เรียกว่าสเปร

ดูhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax


0

ตัวดำเนินการสเปรด (ตัวดำเนินการสามตัว) แนะนำใน ecama script 6 (ES6) .Ecama script (ES6) เป็นตัวห่อของจาวาสคริปต์

ผู้ประกอบการกระจายคุณสมบัตินับได้ในอุปกรณ์ประกอบฉาก this.props = {ชื่อแรก: 'Dan', นามสกุล: 'Abramov', เมือง: 'New York', ประเทศ: 'USA'}

{... this.props} = {ชื่อแรก: 'Dan', นามสกุล: 'Abramov', เมือง: 'New York', ประเทศ: 'USA'}

แต่ตัวดำเนินการกระจายฟีเจอร์หลักใช้สำหรับประเภทการอ้างอิง

For example
let person= {
    name: 'Alex',
    age: 35 
}
person1= person;

person1.name = "Raheel";

console.log( person.name); // output: Raheel

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

 let person= {
        name: 'Alex',
        age: 35 
    }
person2 = {...person};

person2.name = "Shahzad";

console.log(person.name); // output: Alex

0

หากคุณมีอาร์เรย์ขององค์ประกอบและคุณต้องการที่จะแสดงองค์ประกอบที่คุณเพิ่งใช้ ... arrayemaments และมันจะทำซ้ำองค์ประกอบทั้งหมด


0

...(สามจุดใน Javascript) เรียกว่า Spread Syntax หรือ Spread Operator สิ่งนี้อนุญาตให้ iterable เช่นนิพจน์อาร์เรย์หรือสตริงที่จะขยายหรือการแสดงออกวัตถุที่จะขยายทุกที่ สิ่งนี้ไม่เฉพาะเจาะจงสำหรับการโต้ตอบ มันเป็นผู้ประกอบการ Javascript

คำตอบทั้งหมดเหล่านี้ที่นี่มีประโยชน์ แต่ฉันต้องการแสดงรายการ Case การใช้งานเชิงปฏิบัติที่เป็นประโยชน์ของไวยากรณ์การแพร่กระจาย (Spread Operator)

1. รวมอาร์เรย์ (เชื่อมต่ออาร์เรย์)

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

var arr1 = ['two', 'three'];
var arr2 = ['one', ...arr1, 'four', 'five'];

// arr2 = ["one", "two", "three", "four", "five"]

2. การคัดลอกอาร์เรย์

เมื่อเราต้องการสำเนาของอาร์เรย์ที่เราใช้ในการมีArray.prototypr.slice ()วิธีการ แต่คุณสามารถทำเช่นเดียวกันกับผู้ดำเนินการแพร่กระจาย

var arr = [1,2,3];
var arr2 = [...arr];
// arr2 = [1,2,3]

3. ฟังก์ชั่นการโทรโดยไม่ต้องสมัคร

ใน ES5 เมื่อต้องการส่งผ่านอาร์เรย์ของตัวเลขสองจำนวนไปยังdoStuff()ฟังก์ชันคุณมักใช้เมธอดFunction.prototype.apply ()ดังนี้:

function doStuff (x, y, z) { }
var args = [0, 1, 2];

// Call the function, passing args
doStuff.apply(null, args);

อย่างไรก็ตามโดยใช้ตัวดำเนินการสเปรดคุณสามารถส่งผ่านอาร์เรย์ไปยังฟังก์ชันได้

doStuff(...args);

4. อาร์เรย์การทำลายล้าง

คุณสามารถใช้ destructuring และตัวดำเนินการส่วนที่เหลือร่วมกันเพื่อแยกข้อมูลออกเป็นตัวแปรตามที่คุณต้องการ:

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

5. ฟังก์ชันอาร์กิวเมนต์เป็นพารามิเตอร์ที่เหลือ

ES6 ยังมีจุดสามจุด (... ) ซึ่งเป็นพารามิเตอร์ที่เหลือที่รวบรวมอาร์กิวเมนต์ที่เหลืออยู่ทั้งหมดของฟังก์ชันในอาร์เรย์

function f(a, b, ...args) {
  console.log(args);
}

f(1,2,3,4,5);
// [ 3, 4, 5 ]

6. การใช้ฟังก์ชันทางคณิตศาสตร์

ฟังก์ชั่นใด ๆ ที่ใช้การแพร่กระจายเป็นอาร์กิวเมนต์สามารถใช้งานโดยฟังก์ชั่นที่สามารถยอมรับจำนวนของข้อโต้แย้ง

let numbers = [9, 4, 7, 1];
Math.min(...numbers); // 1

7. การรวมสองวัตถุ

คุณสามารถใช้ตัวดำเนินการการแพร่กระจายเพื่อรวมวัตถุสองอย่าง นี่เป็นวิธีที่ง่ายและสะอาดกว่าในการทำ

var carType = {
  model: 'Toyota',
  yom: '1995'
};

var carFuel = 'Petrol';

var carData = {
  ...carType,
  carFuel
}

console.log(carData); 
// {
//  model: 'Toyota',
//  yom: '1995',
//  carFuel = 'Petrol'
// }

8. แยกสตริงออกเป็นอักขระที่แยกต่างหาก

คุณสามารถใช้ตัวดำเนินการสเปรดเพื่อกระจายสตริงเป็นอักขระแยกต่างหาก

let chars = ['A', ...'BC', 'D'];
console.log(chars); // ["A", "B", "C", "D"]

คุณสามารถคิดถึงวิธีการเพิ่มเติมในการใช้ตัวดำเนินการสเปรด สิ่งที่ฉันระบุไว้ที่นี่เป็นกรณีการใช้งานที่เป็นที่นิยมของมัน


-1

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

let array = [1,2,3]
let array2 = [...array]
// array2 is now filled with the items from array

และด้วยวัตถุ / คีย์:

// lets pass an object as props to a react component
let myParameters = {myKey: 5, myOtherKey: 7}
let component = <MyComponent {...myParameters}/>
// this is equal to <MyComponent myKey=5 myOtherKey=7 />

สิ่งที่เจ๋งจริงๆคือคุณสามารถใช้มันเพื่อหมายถึง "ค่าที่เหลือ"

const myFunc = (value1, value2, ...values) {
    // Some code
}

myFunc(1, 2, 3, 4, 5)
// when myFunc is called, the rest of the variables are placed into the "values" array

-3

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

เช่น:

let a = [1, 2, 3];
let b = [...a, 4, 5, 6];
console.log(b);
> [1, 2, 3, 4, 5, 6]
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.