JavaScript: วิธีส่งผ่านวัตถุด้วยค่า?


98
  • เมื่อส่งผ่านอ็อบเจ็กต์เป็นพารามิเตอร์ JavaScript จะส่งผ่านอ็อบเจ็กต์โดยการอ้างอิงและทำให้ยากที่จะสร้างสำเนาโลคัลของอ็อบเจ็กต์

    var o = {};
    (function(x){
        var obj = x;
        obj.foo = 'foo';
        obj.bar = 'bar';
    })(o)
    

    oจะมี.fooและ.bar.

  • เป็นไปได้ที่จะหลีกเลี่ยงสิ่งนี้โดยการโคลน ตัวอย่างง่ายๆ:

    var o = {};
    
    function Clone(x) {
       for(p in x)
       this[p] = (typeof(x[p]) == 'object')? new Clone(x[p]) : x[p];
    }
    
    (function(x){
        var obj = new Clone(x);
        obj.foo = 'foo';
        obj.bar = 'bar';
    })(o)
    

    oจะไม่มี.fooหรือ.bar.


คำถาม

  1. มีวิธีที่ดีกว่าในการส่งผ่านวัตถุด้วยค่านอกเหนือจากการสร้างสำเนา / โคลนในเครื่องหรือไม่

3
กรณีการใช้งานของคุณต้องการสิ่งนี้คืออะไร?
jondavidjohn

2
การเขียนโปรแกรมสนุก ดูว่าเอ็นจิ้น JS ใหม่ตอบสนองสิ่งนี้หรือไม่ (ในทางเทคนิคคือส่งต่อการอ้างอิงตามค่า) แต่เพื่อความสนุกสนานเป็นหลัก
vol7ron

1
โปรดดูที่JavaScript เป็นภาษาแบบพาส - บาย - อ้างอิงหรือพาส - บาย - ค่า? - JavaScript ไม่ผ่านการอ้างอิง เช่นเดียวกับ Java เมื่อส่งผ่านวัตถุไปยังฟังก์ชันจะส่งผ่านค่า แต่ค่านั้นเป็นการอ้างอิง โปรดดูที่Java pass by reference หรือไม่? .
Richard JP Le Guen

1
เท่าที่ฉันทราบว่าคุณไม่สามารถส่งผ่านวัตถุด้วยค่าได้ แม้ว่าจะมี แต่ก็จะมีการทำโคลนนิ่งที่คุณอ้างถึงข้างต้นดังนั้นไม่มีอะไรจะได้รับที่ฉันเห็น นอกเหนือจากการบันทึกโค้ด 3 บรรทัด
Thor84no

1
@ vol7ron ใช่พวกเขาได้แก้ไขโดยการใช้ลักษณะการออกแบบภาษาอย่างถูกต้อง
jondavidjohn

คำตอบ:


62

ไม่จริง.

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

var o = {};
(function(x){
    var obj = Object.create( x );
    obj.foo = 'foo';
    obj.bar = 'bar';
})(o);

alert( o.foo ); // undefined

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

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

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

var o = {
    baz: []
};
(function(x){
    var obj = Object.create( x );

    obj.baz.push( 'new value' );

})(o);

alert( o.baz[0] );  // 'new_value'

ที่นี่คุณสามารถเห็นได้ว่าเพราะคุณไม่ได้เงาอาร์เรย์ที่bazเกี่ยวกับการoที่มีbazคุณสมบัติในobjการo.bazอาร์เรย์ได้รับการแก้ไข

ดังนั้นคุณจะต้องเงาก่อน:

var o = {
    baz: []
};
(function(x){
    var obj = Object.create( x );

    obj.baz = [];
    obj.baz.push( 'new value' );

})(o);

alert( o.baz[0] );  // undefined

3
+1 ฉันจะแนะนำObject.createในคำตอบของฉันด้วย แต่ฉันไม่อยากอธิบายความตื้นของสำเนา ;-)
Andy E

+1 ฉันลืมเรื่องนี้ไปแล้ว var obj = new Object(x)ผมไม่พยายาม สำหรับฉันฉันคิดว่าnew Object(x)จะแสดงObject.create(x)โดยปริยาย - น่าสนใจ
vol7ron

1
@ vol7ron: ใช่new Object(x)เพียงแค่ถ่มน้ำลายกลับออกวัตถุเดียวกัน(ตามที่คุณอาจสังเกตเห็น) คงจะดีไม่น้อยหากมีวิธีโคลนแบบพื้นเมือง ไม่แน่ใจว่ามีผลงานอะไรหรือเปล่า
user113716

45

ตรวจสอบคำตอบนี้https://stackoverflow.com/a/5344074/746491

ในระยะสั้นJSON.parse(JSON.stringify(obj))เป็นวิธีที่รวดเร็วในการคัดลอกวัตถุของคุณหากวัตถุของคุณสามารถต่ออนุกรมกับ json ได้


2
ฉันมักจะหลีกเลี่ยงปัญหานี้เป็นวัตถุที่ไม่สามารถต่อเนื่องและเนื่องจากในเบราว์เซอร์กลางวัยเช่น IE7 / 8, JSONไม่ได้รวมและความต้องการที่จะกำหนด - Cloneเช่นกันอาจจะอธิบายเพิ่มเติมที่มีชื่อเหมือน อย่างไรก็ตามฉันสงสัยว่าความคิดเห็นของฉันอาจเปลี่ยนไปในอนาคตเนื่องจาก JSON ถูกรวมเข้ากับซอฟต์แวร์ที่ไม่ใช้เบราว์เซอร์เช่นฐานข้อมูลและ IDE อย่างมาก
vol7ron

1
หากไม่มีฟังก์ชันและอ็อบเจ็กต์วันที่โซลูชัน JSON.parse น่าจะดีที่สุด stackoverflow.com/questions/122102/…
Herr_Hansen

จริงๆ?!? ทำให้เป็นอนุกรมเป็น JSON เพียงเพื่อสร้างสำเนาวัตถุหรือไม่ อีกเหตุผลหนึ่งที่ทำให้เกลียดภาษาไร้สาระนี้
RyanNerd

1
การทำให้อนุกรม JSON เป็นวิธีที่รวดเร็วในการคัดลอกหรือไม่? ตามเอกสาร NodeJS การจัดการ JSON เป็นงานที่ต้องใช้ CPU มากที่สุด nodejs.org/en/docs/guides/dont-block-the-event-loop/…
harshad

40

นี่คือฟังก์ชั่นโคลนที่จะทำสำเนาลึกของวัตถุ:

function clone(obj){
    if(obj == null || typeof(obj) != 'object')
        return obj;

    var temp = new obj.constructor(); 
    for(var key in obj)
        temp[key] = clone(obj[key]);

    return temp;
}

ตอนนี้คุณสามารถใช้สิ่งนี้:

(function(x){
    var obj = clone(x);
    obj.foo = 'foo';
    obj.bar = 'bar';
})(o)

3
นี่เป็นคำตอบที่ลึกซึ้ง
นาธาน

สวย! คำตอบที่ดีที่สุด IMO
ganders

24

ใช้ Object.assign()

ตัวอย่าง:

var a = {some: object};
var b = new Object;
Object.assign(b, a);
// b now equals a, but not by association.

ตัวอย่างที่สะอาดกว่าที่ทำสิ่งเดียวกัน:

var a = {some: object};
var b = Object.assign({}, a);
// Once again, b now equals a.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign


4
Better:var b = Object.assign({}, a);
Bergi

เห็นด้วย กำลังอัปเดตคำตอบตามนั้น นอกจากนี้เบราว์เซอร์บางตัวไม่สนับสนุนวิธีการกำหนด () ขึ้นอยู่กับความต้องการความเข้ากันได้ของคุณอาจจำเป็นต้องใช้ polyfill เช่นเดียวกับ MDN
Brandon

3
@Brandon ในลิงค์ที่คุณระบุมันให้คำเตือนสำหรับการโคลนนิ่งแบบลึก: "สำหรับการโคลนนิ่งแบบลึกเราจำเป็นต้องใช้ทางเลือกอื่นเนื่องจาก Object.assign () จะคัดลอกค่าคุณสมบัติหากค่าต้นทางเป็นการอ้างอิงถึงวัตถุ คัดลอกเฉพาะค่าอ้างอิงเท่านั้น "
pwilcox

2
วิธีนี้ใช้งานได้ แต่โปรดทราบว่าจะไม่ทำการคัดลอกวัตถุใด ๆ ที่อยู่ภายในอย่างลึกล้ำaจะถูกคัดลอกเป็นข้อมูลอ้างอิง
Stoinov

16

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

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

JavaScript เป็นเพียงค่า pass-by-value ... เพียงแค่ว่าค่าที่ส่งผ่านไปอาจเป็นการอ้างอิงถึงบางสิ่ง


2
เฮ้ AndyE! ฉันไม่สับสนกับสิ่งนั้นฉันหวังว่า JS จะทำการโคลนนิ่งโดยค่าเริ่มต้น มีความไร้ประสิทธิภาพอย่างมากในการโคลนนิ่งตัวเองดังนั้นหากเครื่องยนต์ทำได้ฉันมั่นใจว่ามันจะดีกว่านี้ ฉันสงสัยว่าความต้องการ / ความต้องการนั้นเกินผลประโยชน์
vol7ron

13
ใน JS เมื่อผู้คนพูดโดยอ้างอิงแทนที่จะเป็นตามค่าพวกเขาหมายความว่าค่าเป็นเหมือนตัวชี้แทนที่จะเป็นซ้ำ นั่นเป็นศัพท์แสงที่ค่อนข้างดี
Erik Reppen

4
@Erik: ในความเห็นที่ต่ำต้อยของฉันฉันคิดว่ามันจะดีกว่าที่จะกำหนดให้ชัดเจนกว่านี้เพื่อไม่ให้ผู้มาใหม่สับสนกับภาษา เพียงเพราะบางสิ่งเป็นที่ยอมรับไม่ได้หมายความว่ามันเหมาะสมหรือถูกต้องในทางเทคนิค (เพราะมันไม่ใช่) ผู้คนมักพูดว่า "โดยการอ้างอิง" เพราะมันง่ายกว่าสำหรับพวกเขาที่จะพูดมากกว่าการอธิบายว่ามันได้ผลจริงอย่างไร
Andy E

6
ค่านี้เป็นการอ้างอิงตำแหน่งในหน่วยความจำ ท้ายที่สุดแล้วคุณยังคงดำเนินการกับรายการเดิมในหน่วยความจำแทนที่จะทำงานกับสำเนา การทำให้ความแตกต่างไม่ชัดเจนนั้นน่าจะช่วยผู้มาใหม่ได้อย่างไร? นี่คือวิธีที่อธิบายไว้ในหนังสือเทคโนโลยีจำนวนมากรวมถึงคู่มือที่เชื่อถือได้ของ O'Reilly ซึ่งตอนนี้เป็นฉบับที่ห้า (OT: และอัปเดตอย่างอ่อนมาก)
Erik Reppen

1
@AndyE ฉันอ่านอีกเล็กน้อยเพื่อดูว่าเอะอะเกี่ยวกับอะไร IMO นี่เหมือนกับประเด็นที่ว่า JS มี OOP "จริง" หรือเราสามารถเรียกสิ่งที่ถูกต้องว่า "วิธีการ" เมื่อเทียบกับภาษาอื่น ๆ ฉันไม่แน่ใจจริงๆว่ามันจะเป็นไปได้ที่จะปฏิบัติต่อ var เป็นการเขียนลงในวัตถุเดียวกันโดยตรงในหน่วยความจำแทนที่จะเขียนทับตัวชี้ที่คัดลอกในภาษาที่ใช้การปิดด้วยการแยกสาขาพฤติกรรมของผู้ดำเนินการมอบหมายประสิทธิภาพ ความแตกต่างของพฤติกรรมที่แท้จริงเพียงอย่างเดียวในสิ่งที่เราหมายถึงใน JS เทียบกับภาษาอื่น ๆ คือสิ่งที่เกิดขึ้นเมื่อคุณใช้ตัวดำเนินการกำหนด
Erik Reppen

16

ใช้สิ่งนี้

x = Object.create(x1);

xและx1จะเป็นสองวัตถุที่แตกต่างกันการเปลี่ยนแปลงxจะไม่เปลี่ยนแปลงx1


ฉันจบลงด้วยการใช้ Object.assign () สำหรับกรณีทดสอบอย่างง่าย. create () ใช้งานได้ แต่สำหรับกรณีที่ซับซ้อนมากขึ้น (ซึ่งฉันยังหารูปแบบไม่พบ) มันยังคงอ้างถึงที่อยู่เดิม
Coisox

1
มันจะไม่เปลี่ยนแปลงเฉพาะในกรณีที่ค่าของวัตถุไม่ได้ถูกจัดเก็บโดยการอ้างอิงกล่าวคือเป็นประเภทข้อมูลที่มีอยู่ก่อนเช่นจำนวนหรือบูลีน ตัวอย่างเช่นพิจารณาโค้ดด้านล่าง a = {x: [12], y: []}; b = Object.create (a); bxpush (12); console.log (ขวาน);
Jjagwe Dennis

9

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

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

function ShallowCopy(o) {
  var copy = Object.create(o);
  for (prop in o) {
    if (o.hasOwnProperty(prop)) {
      copy[prop] = o[prop];
    }
  }
  return copy;
}

1
+1 สำหรับ "ส่งผ่านค่าเสมอ" แม้ว่าฉันจะชอบใช้Call by Object Sharing (ตรงข้ามกับ "Call by Value [of the Reference]") และเลื่อนระดับ "ค่า" เป็น "ตัววัตถุเอง" (โดยมีข้อสังเกตว่า วัตถุไม่ได้ถูกคัดลอก / โคลน / ทำซ้ำ) เนื่องจากการอ้างอิงเป็นเพียงรายละเอียดการนำไปใช้งานและไม่เปิดเผยต่อ JavaScript (หรือกล่าวถึงโดยตรงในข้อกำหนด!)

ฉันมีปัญหาในการเพิ่มคุณสมบัติให้กับวัตถุที่ฉันได้รับจากการเชื่อมต่อระยะไกล (ฉันคิดว่านั่นอาจเป็นปัญหาที่ฉันไม่สามารถเพิ่มคุณสมบัติใด ๆ ให้กับวัตถุนั้นได้) ดังนั้นฉันจึงลองใช้ฟังก์ชันชัดตื้นนี้และได้รับข้อผิดพลาดนี้ - ต้นแบบวัตถุ อาจเป็นเพียง Object หรือ null ที่ var copy = Object.create (o); ความคิดใด ๆ ที่จะแก้ปัญหาของฉัน
Harshit Laddha

นี่ไม่ใช่สำเนาลึก?
River Tam

@RiverTam ไม่ใช่ไม่ใช่สำเนาลึกเพราะไม่ได้โคลนวัตถุภายในวัตถุ อย่างไรก็ตามคุณสามารถทำให้เป็นสำเนาลึกได้อย่างง่ายดายเพียงแค่เรียกตัวเองซ้ำ ๆ บนวัตถุย่อยแต่ละชิ้น
ABPerson

7

เพื่อเป็นการคำนึงถึงผู้ใช้ jQuery นอกจากนี้ยังมีวิธีดำเนินการนี้ด้วยวิธีง่ายๆโดยใช้กรอบ อีกวิธีหนึ่งที่ jQuery ทำให้ชีวิตของเราง่ายขึ้นเล็กน้อย

var oShallowCopy = jQuery.extend({}, o);
var oDeepCopy    = jQuery.extend(true, {}, o); 

อ้างอิง:


อ่า - คุณค้นพบคำถามเก่า ๆ นี้แล้ว :) ฉันคิดว่าคำถามเดิมเป็นการสำรวจภาษา JS มากกว่า ดูเหมือนว่าแม้คำศัพท์ของฉันก็กลับมาที่อ่อนแอแล้วตั้งแต่ตัวอย่างของฉันเป็นของสำเนาลึกมากกว่าโคลน แต่ดูเหมือนว่าวัตถุ / แฮชอาจถูกส่งผ่านโดยการอ้างอิงเท่านั้นซึ่งเป็นเรื่องปกติในภาษาสคริปต์
vol7ron

1
:) พบว่ามันกำลังมองหาฟังก์ชันการทำงานที่แน่นอน ฉันมีวัตถุข้อมูลที่ต้องการคัดลอกเพื่อแก้ไขก่อนที่จะส่งในขณะที่ยังคงใช้วัตถุดั้งเดิมอยู่ ฉันชอบโซลูชัน JS ดั้งเดิมและจะใช้ในไลบรารีพื้นฐานของฉันเอง แต่โซลูชัน jQuery เป็นการแก้ไขชั่วคราวของฉัน คำตอบที่ได้รับการยอมรับนั้นยอดเยี่ยมมาก : D
Brett Weber

6

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

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

var person = { Name: 'John', Age: '21', Gender: 'Male' };

var holder = JSON.stringify(person);
// value of holder is "{"Name":"John","Age":"21","Gender":"Male"}"
// note that holder is a new string object

var person_copy = JSON.parse(holder);
// value of person_copy is { Name: 'John', Age: '21', Gender: 'Male' };
// person and person_copy now have the same properties and data
// but are referencing two different objects

2
ใช่นี่คือตัวเลือกสำหรับการแปลง / แปลงซ้ำอย่างง่าย โดยทั่วไปการทำงานกับสตริงจะไม่มีประสิทธิภาพมาก แม้ว่าฉันจะไม่ได้ประเมินประสิทธิภาพของการแยกวิเคราะห์ JSON ในบางครั้ง โปรดทราบว่าแม้ว่าจะใช้ได้กับวัตถุธรรมดา แต่วัตถุที่มีฟังก์ชันเป็นค่าจะสูญเสียเนื้อหาไป
vol7ron

ฉันได้เปรียบเทียบสิ่งนี้จริงและเคยเห็นคนอื่นทำและเนื่องจากประสิทธิภาพของ javascripts json engine วิธีนี้เป็นหนึ่งในวิธีที่เร็วที่สุดที่คุณสามารถทำได้โดยไม่ต้องนำเข้าในห้องสมุดขนาดใหญ่เขียนโค้ดจำนวนมากหรือไม่ทำ สำเนาลึกจริง
tedivm

4

การใช้ตัวดำเนินการสเปรดเช่นobj2 = { ...obj1 } Will มีค่าเหมือนกัน แต่การอ้างอิงต่างกัน


2
ใหม่สำหรับ javascript ที่นี่ ตัวดำเนินการสเปรดสร้างมูลค่าใหม่แทนการคัดลอกโดยการอ้างอิง? เหตุใดจึงถูกลดคะแนนลง
jo3birdtalk

2
แวบแรกมันได้ผลสำหรับฉัน แต่ฉันพบว่ามันเป็นเพียงชั้นแรกของตัวแปร ยกตัวอย่างเช่นการทำงานออกเมื่อlet a = {value: "old"} let b = [...a] b.value = "new"และจะขจะ{value: "old"} {value: "new"}แต่ก็ไม่ได้ผลงานออกมาเมื่อlet a = [{value: "old"}] let b = [...a] b[0].value = "new"และจะขจะ[{value: "new"}] [{value: "new"}]
Brady Huang

ใช่มันทำสำเนาตื้น หากคุณมีวัตถุที่ซ้อนกันคุณต้องทำสำเนาแบบลึก เพื่อความเรียบง่ายคุณสามารถใช้ฟังก์ชั่นโคลนและ deepClone ของ lodash
Geetanshu Gulati

3

ฉันต้องการคัดลอกวัตถุตามค่า (ไม่อ้างอิง) และฉันพบว่าหน้านี้มีประโยชน์:

วิธีใดที่มีประสิทธิภาพที่สุดในการโคลนวัตถุใน JavaScript อย่างมีประสิทธิภาพที่สุด . โดยเฉพาะอย่างยิ่งการโคลนวัตถุด้วยรหัสต่อไปนี้โดย John Resig:

//Shallow copy
var newObject = jQuery.extend({}, oldObject);
// Deep copy
var newObject = jQuery.extend(true, {}, oldObject);

คำถามเกี่ยวกับ JavaScript ไม่ใช่ไลบรารี jQuery
j08691

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

จะไม่ช่วยโปรแกรมเมอร์คนใดที่พยายามทำบนเซิร์ฟเวอร์ ดังนั้น - ไม่ ไม่ใช่คำตอบที่ถูกต้อง
Tomasz Gałkowski

3

ด้วยไวยากรณ์ ES6:

let obj = Object.assign({}, o);


3
พูดถึง @galkowskit ดีมาก ปัญหาที่ใหญ่ที่สุด (ดีกว่า: สิ่งที่ควรทราบ ) Object.assignคือมันไม่ได้ทำสำเนาลึก
vol7ron

1

เมื่อคุณต้มลงไปมันเป็นเพียงพร็อกซีที่ซับซ้อนเกินไป แต่บางทีCatch-All Proxiesสามารถทำได้?

var o = {
    a: 'a',
    b: 'b',
    func: function() { return 'func'; }
};

var proxy = Proxy.create(handlerMaker(o), o);

(function(x){
    var obj = x;
    console.log(x.a);
    console.log(x.b);
    obj.foo = 'foo';
    obj.bar = 'bar';
})(proxy);

console.log(o.foo);

function handlerMaker(obj) {
  return {
   getOwnPropertyDescriptor: function(name) {
     var desc = Object.getOwnPropertyDescriptor(obj, name);
     // a trapping proxy's properties must always be configurable
     if (desc !== undefined) { desc.configurable = true; }
     return desc;
   },
   getPropertyDescriptor:  function(name) {
     var desc = Object.getOwnPropertyDescriptor(obj, name); // not in ES5
     // a trapping proxy's properties must always be configurable
     if (desc !== undefined) { desc.configurable = true; }
     return desc;
   },
   getOwnPropertyNames: function() {
     return Object.getOwnPropertyNames(obj);
   },
   getPropertyNames: function() {
     return Object.getPropertyNames(obj);                // not in ES5
   },
   defineProperty: function(name, desc) {

   },
   delete:       function(name) { return delete obj[name]; },   
   fix:          function() {}
  };
}

ริชาร์ดฉันตอบช้าไปหน่อย :) แต่ฉันคิดว่าฉันไม่เคยทำด้วยเหตุผลบางประการ: ฉันกำลังมองหาน้ำตาลซินแทติกที่ทำให้ JS สามารถส่งผ่านวัตถุในรูปแบบต่างๆ คำตอบของคุณดูยาวและฉันรู้สึกว่าคุณใช้ "พร็อกซี" 3 ปีต่อมาและฉันก็ยังคงใช้งานอยู่ บางทีฉันอาจไม่ได้ให้ความสนใจมากพอในชั้นเรียน แต่เช่นเดียวกับการสร้างเครือข่ายฉันคิดว่าผู้รับมอบฉันทะใน CS ควรทำหน้าที่เป็นตัวกลาง บางทีมันก็อยู่ที่นี่เช่นกันและฉันคิดไม่ถูกว่ามันเป็นสื่อกลางระหว่างอะไร
vol7ron

0

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

var objectCopy = lodash.merge({}, originalObject);

https://lodash.com/docs#merge

https://www.npmjs.com/package/lodash.merge


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