Sorulduğu gibi, burada özyinelemeli nesne karşılaştırma işlevi. Ve biraz daha. Böyle bir işlevin birincil kullanımının nesne denetimi olduğunu varsayarsak, söyleyecek bir şeyim var. Bazı farklılıklar alakasız olduğunda tam derin karşılaştırma kötü bir fikirdir. Örneğin, TDD iddialarında kör derin karşılaştırma testleri gereksiz kırılgan hale getirir. Bu nedenle, çok daha değerli bir kısmi fark tanıtmak istiyorum . Bu konuya önceki bir katkının özyinelemeli bir analogudur. O bulunmayan anahtarları yok sayar a
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] : [])),
[]);
Tam olarak ne için istediğini diğer özellikleri, tolere ederken BDiff beklenen değerler için kontrol sağlar otomatik muayene. Bu, her türlü gelişmiş iddiaların oluşturulmasına izin verir. Örneğin:
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);
Komple çözüme dönülüyor. Bdiff ile tam bir geleneksel fark oluşturmak önemsizdir:
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));
};
İki karmaşık nesnede yukarıdaki işlevin çalıştırılması buna benzer bir şey çıkarır:
[
" < 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"
]
Son olarak, değerlerin nasıl farklılaştığına bir göz atmak için , fark çıktısını doğrudan değerlendirmek () isteyebiliriz . Bunun için, sözdizimsel olarak doğru yolların çıktısını veren daha çirkin bir bdiff sürümüne ihtiyacımız var :
// 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)))));
Bu şuna benzer bir şey çıkarır:
[" | 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 lisansı;)