ตามที่ถูกถามนี่เป็นฟังก์ชันเปรียบเทียบวัตถุแบบเรียกซ้ำ และอีกเล็กน้อย สมมติว่าการใช้งานหลักของฟังก์ชั่นดังกล่าวคือการตรวจสอบวัตถุฉันมีสิ่งที่จะพูด การเปรียบเทียบเชิงลึกอย่างสมบูรณ์เป็นความคิดที่ไม่ดีเมื่อความแตกต่างบางอย่างไม่เกี่ยวข้อง ตัวอย่างเช่นการเปรียบเทียบความลึกของคนตาบอดในการยืนยัน TDD ทำให้การทดสอบที่ไม่จำเป็นเปราะ สำหรับเหตุผลที่ผมอยากจะแนะนำให้มีคุณค่ามากขึ้นdiff บางส่วน มันเป็นอะนาล็อกแบบเรียกซ้ำของการสนับสนุนก่อนหน้าในหัวข้อนี้ จะละเว้นคีย์ไม่ได้อยู่ใน
var bdiff = (a, b) =>
_.reduce(a, (res, val, key) =>
res.concat((_.isPlainObject(val) || _.isArray(val)) && b
? bdiff(val, b[key]).map(x => key + '.' + x)
: (!b || val != b[key] ? [key] : [])),
[]);
BDiff อนุญาตให้ตรวจสอบค่าที่คาดหวังในขณะที่ยอมรับคุณสมบัติอื่น ๆ ซึ่งเป็นสิ่งที่คุณต้องการสำหรับการตรวจสอบอัตโนมัติ สิ่งนี้ทำให้สามารถสร้างการยืนยันขั้นสูงทุกชนิด ตัวอย่างเช่น:
var diff = bdiff(expected, actual);
// all expected properties match
console.assert(diff.length == 0, "Objects differ", diff, expected, actual);
// controlled inequality
console.assert(diff.length < 3, "Too many differences", diff, expected, actual);
กลับไปที่โซลูชันที่สมบูรณ์ การสร้างความแตกต่างแบบดั้งเดิมกับ bdiff เป็นเรื่องเล็กน้อย:
function diff(a, b) {
var u = bdiff(a, b), v = bdiff(b, a);
return u.filter(x=>!v.includes(x)).map(x=>' < ' + x)
.concat(u.filter(x=>v.includes(x)).map(x=>' | ' + x))
.concat(v.filter(x=>!u.includes(x)).map(x=>' > ' + x));
};
การเรียกใช้ฟังก์ชันด้านบนของวัตถุที่ซับซ้อนสองรายการจะให้ผลลัพธ์คล้ายกัน
[
" < components.0.components.1.components.1.isNew",
" < components.0.cryptoKey",
" | components.0.components.2.components.2.components.2.FFT.min",
" | components.0.components.2.components.2.components.2.FFT.max",
" > components.0.components.1.components.1.merkleTree",
" > components.0.components.2.components.2.components.2.merkleTree",
" > components.0.components.3.FFTResult"
]
ในที่สุดเพื่อที่จะได้เห็นว่าค่าแตกต่างกันอย่างไรเราอาจต้องการEval ()เอาท์พุตโดยตรง สำหรับสิ่งนั้นเราต้องการbdiffรุ่น uglier ที่ให้เส้นทางที่ถูกต้องทางไวยากรณ์:
// provides syntactically correct output
var bdiff = (a, b) =>
_.reduce(a, (res, val, key) =>
res.concat((_.isPlainObject(val) || _.isArray(val)) && b
? bdiff(val, b[key]).map(x =>
key + (key.trim ? '':']') + (x.search(/^\d/)? '.':'[') + x)
: (!b || val != b[key] ? [key + (key.trim ? '':']')] : [])),
[]);
// now we can eval output of the diff fuction that we left unchanged
diff(a, b).filter(x=>x[1] == '|').map(x=>[x].concat([a, b].map(y=>((z) =>eval('z.' + x.substr(3))).call(this, y)))));
ที่จะส่งออกสิ่งที่คล้ายกับนี้:
[" | components[0].components[2].components[2].components[2].FFT.min", 0, 3]
[" | components[0].components[2].components[2].components[2].FFT.max", 100, 50]
ใบอนุญาต MIT;)