คำตอบ:
นี่คือวิธีextend/ การassignทำงาน: สำหรับแต่ละคุณสมบัติในแหล่งที่มาให้คัดลอกค่าตามที่เป็นไปยังปลายทาง หากค่าคุณสมบัติเป็นวัตถุเองก็จะไม่มีคุณสมบัติการแวะเวียนแบบเรียกซ้ำ วัตถุทั้งหมดจะถูกนำมาจากแหล่งที่มาและกำหนดไว้ในปลายทาง
นี่เป็นวิธีการmergeทำงาน: สำหรับแต่ละคุณสมบัติในแหล่งข้อมูลให้ตรวจสอบว่าคุณสมบัตินั้นเป็นวัตถุเอง ถ้าเป็นไปแล้วซ้ำและพยายามแมปคุณสมบัติวัตถุลูกจากต้นทางไปยังปลายทาง ดังนั้นเราจึงรวมลำดับชั้นของวัตถุจากต้นทางไปยังปลายทาง ในขณะที่สำหรับextend/ assignมันเป็นสำเนาของคุณสมบัติในระดับง่าย ๆ จากต้นทางไปยังปลายทาง
นี่คือ JSBin ง่าย ๆ ที่จะทำให้คริสตัลนี้ใส: http://jsbin.com/uXaqIMa/2/edit?js,console
นี่คือเวอร์ชั่นที่ซับซ้อนยิ่งขึ้นซึ่งรวมถึงอาเรย์ในตัวอย่างด้วย: http://jsbin.com/uXaqIMa/1/edit?js,console
var combined = merge({}, src, dest)
_.merge(object, [sources], [customizer], [thisArg])_.assign(object, [sources], [customizer], [thisArg])_.extend(object, [sources], [customizer], [thisArg])_.defaults(object, [sources])_.defaultsDeep(object, [sources])_.extendเป็นชื่อแทน_.assignดังนั้นจึงเหมือนกันnullเดียวกัน_.defaultsและ_.defaultsDeepประมวลผลข้อโต้แย้งในลำดับย้อนกลับเมื่อเปรียบเทียบกับข้ออื่น (แม้ว่าอาร์กิวเมนต์แรกยังเป็นวัตถุเป้าหมาย)_.mergeและ_.defaultsDeepจะรวมวัตถุลูกและวัตถุอื่น ๆ จะเขียนทับในระดับราก_.assignและ_.extendจะเขียนทับค่าด้วยundefined_.assign ({}, { a: 'a' }, { a: 'bb' }) // => { a: "bb" }
_.merge ({}, { a: 'a' }, { a: 'bb' }) // => { a: "bb" }
_.defaults ({}, { a: 'a' }, { a: 'bb' }) // => { a: "a" }
_.defaultsDeep({}, { a: 'a' }, { a: 'bb' }) // => { a: "a" }
_.assignจับundefinedแต่คนอื่น ๆ จะข้ามมัน_.assign ({}, { a: 'a' }, { a: undefined }) // => { a: undefined }
_.merge ({}, { a: 'a' }, { a: undefined }) // => { a: "a" }
_.defaults ({}, { a: undefined }, { a: 'bb' }) // => { a: "bb" }
_.defaultsDeep({}, { a: undefined }, { a: 'bb' }) // => { a: "bb" }
nullเดียวกัน_.assign ({}, { a: 'a' }, { a: null }) // => { a: null }
_.merge ({}, { a: 'a' }, { a: null }) // => { a: null }
_.defaults ({}, { a: null }, { a: 'bb' }) // => { a: null }
_.defaultsDeep({}, { a: null }, { a: 'bb' }) // => { a: null }
_.mergeและ_.defaultsDeepจะรวมวัตถุลูก_.assign ({}, {a:{a:'a'}}, {a:{b:'bb'}}) // => { "a": { "b": "bb" }}
_.merge ({}, {a:{a:'a'}}, {a:{b:'bb'}}) // => { "a": { "a": "a", "b": "bb" }}
_.defaults ({}, {a:{a:'a'}}, {a:{b:'bb'}}) // => { "a": { "a": "a" }}
_.defaultsDeep({}, {a:{a:'a'}}, {a:{b:'bb'}}) // => { "a": { "a": "a", "b": "bb" }}
_.assign ({}, {a:['a']}, {a:['bb']}) // => { "a": [ "bb" ] }
_.merge ({}, {a:['a']}, {a:['bb']}) // => { "a": [ "bb" ] }
_.defaults ({}, {a:['a']}, {a:['bb']}) // => { "a": [ "a" ] }
_.defaultsDeep({}, {a:['a']}, {a:['bb']}) // => { "a": [ "a" ] }
a={a:'a'}; _.assign (a, {b:'bb'}); // a => { a: "a", b: "bb" }
a={a:'a'}; _.merge (a, {b:'bb'}); // a => { a: "a", b: "bb" }
a={a:'a'}; _.defaults (a, {b:'bb'}); // a => { a: "a", b: "bb" }
a={a:'a'}; _.defaultsDeep(a, {b:'bb'}); // a => { a: "a", b: "bb" }
หมายเหตุ: ตามที่ @Mistic ชี้ให้เห็นว่า Lodash ใช้อาร์เรย์เป็นวัตถุที่มีคีย์เป็นดัชนีในอาร์เรย์
_.assign ([], ['a'], ['bb']) // => [ "bb" ]
_.merge ([], ['a'], ['bb']) // => [ "bb" ]
_.defaults ([], ['a'], ['bb']) // => [ "a" ]
_.defaultsDeep([], ['a'], ['bb']) // => [ "a" ]
_.assign ([], ['a','b'], ['bb']) // => [ "bb", "b" ]
_.merge ([], ['a','b'], ['bb']) // => [ "bb", "b" ]
_.defaults ([], ['a','b'], ['bb']) // => [ "a", "b" ]
_.defaultsDeep([], ['a','b'], ['bb']) // => [ "a", "b" ]
_.extend is an alias for _.assign, so they are identicalขัดแย้งกับOnly _.assign will overwrite a value with undefined
ข้อแตกต่างอีกประการที่ควรคำนึงถึงคือการจัดการundefinedค่า:
mergeInto = { a: 1}
toMerge = {a : undefined, b:undefined}
lodash.extend({}, mergeInto, toMerge) // => {a: undefined, b:undefined}
lodash.merge({}, mergeInto, toMerge) // => {a: 1, b:undefined}
ดังนั้นmergeจะไม่รวมundefinedค่าเป็นค่าที่กำหนด
mergeIntoมีคุณสมบัติที่toMergeไม่ได้มีก็จะรักษาคุณสมบัติเหล่านั้น ในกรณีนี้มันจะไม่ลอกแบบ
การพิจารณาสิ่งที่พวกเขาทำจากมุมมองทางความหมายอาจเป็นประโยชน์เช่นกัน
will assign the values of the properties of its second parameter and so on,
as properties with the same name of the first parameter. (shallow copy & override)
merge is like assign but does not assign objects but replicates them instead.
(deep copy)
provides default values for missing values.
so will assign only values for keys that do not exist yet in the source.
works like _defaults but like merge will not simply copy objects
and will use recursion instead.
ฉันเชื่อว่าการเรียนรู้ที่จะคิดวิธีการเหล่านั้นจากมุมมองเชิงความหมายจะช่วยให้คุณ "คาดเดา" ได้ดีขึ้นว่าอะไรจะเป็นพฤติกรรมสำหรับสถานการณ์ที่แตกต่างกันทั้งหมดของค่าที่มีอยู่และไม่ได้มีอยู่
หากคุณต้องการสำเนาลึกที่ไม่มีการแทนที่ในขณะที่ยังคงมีobjการอ้างอิงเดียวกัน
obj = _.assign(obj, _.merge(obj, [source]))