npm i merge-anything
Gabungkan objek & tipe lainnya secara rekursif. Didukung sepenuhnya oleh TypeScript ! Integrasi sederhana & kecil.
Saya membuat paket ini karena saya mencoba banyak paket serupa yang melakukan penggabungan/penggabungan mendalam/penetapan objek rekursif, dll. Tetapi semua memiliki keunikannya sendiri, dan semuanya merusak hal-hal yang tidak seharusnya mereka hancurkan ... ?
Saya mencari:
Object.assign()
tetapi dalam Yang terakhir ini sangat penting! Dalam JavaScript hampir semuanya adalah objek , tentu saja, tapi saya tidak ingin fungsi penggabungan mencoba menggabungkan misalnya. dua instance new Date()
! Begitu banyak perpustakaan menggunakan kelas khusus yang membuat objek dengan prototipe khusus, dan semua objek tersebut rusak saat mencoba menggabungkannya. Jadi kita harus berhati-hati!
merge-anything akan menggabungkan objek dan properti bersarang, tetapi hanya selama itu adalah "objek biasa". Segera setelah sub-prop bukan merupakan "objek biasa" dan memiliki prototipe khusus, ia akan menyalin instance tersebut ke "sebagaimana adanya". ♻️
import { merge } from 'merge-anything'
const starter = { name : 'Squirtle' , types : { water : true } }
const newValues = { name : 'Wartortle' , types : { fighting : true } , level : 16 }
const evolution = merge ( starter , newValues , { is : 'cool' } )
// returns {
// name: 'Wartortle',
// types: { water: true, fighting: true },
// level: 16,
// is: 'cool'
// }
Pada contoh di atas, jika Anda menggunakan TypeScript, dan mengarahkan kursor ke evolution
, Anda sebenarnya dapat melihat tipe objek baru Anda saat itu juga. Ini sangat berguna, karena Anda dapat menggabungkan berbagai hal, dan tanpa any
, TypeScript akan mengetahui secara persis seperti apa tampilan objek yang baru Anda gabungkan!
Tipe kembalian dari fungsi merge()
juga dapat digunakan sebagai utilitas TypeScript:
import type { Merge } from 'merge-anything'
type A1 = { name : string }
type A2 = { types : { water : boolean } }
type A3 = { types : { fighting : boolean } }
type Result = Merge < A1 , [ A2 , A3 ] >
Paket ini akan menelusuri objek biasa secara rekursif dan menggabungkan nilainya ke objek baru.
Harap dicatat bahwa paket ini mengenali objek JavaScript khusus seperti instance kelas. Dalam kasus seperti itu, ia tidak akan menggabungkannya secara rekursif seperti objek, tetapi menugaskan kelas ke objek baru "sebagaimana adanya"!
// all passed objects do not get modified
const a = { a : 'a' }
const b = { b : 'b' }
const c = { c : 'c' }
const result = merge ( a , b , c )
// a === {a: 'a'}
// b === {b: 'b'}
// c === {c: 'c'}
// result === {a: 'a', b: 'b', c: 'c'}
// However, be careful with JavaScript object references with nested props. See below: A note on JavaScript object references
// arrays get overwritten
// (for "concat" logic, see Extensions below)
merge ( { array : [ 'a' ] } , { array : [ 'b' ] } ) // returns {array: ['b']}
// empty objects merge into objects
merge ( { obj : { prop : 'a' } } , { obj : { } } ) // returns {obj: {prop: 'a'}}
// but non-objects overwrite objects
merge ( { obj : { prop : 'a' } } , { obj : null } ) // returns {obj: null}
// and empty objects overwrite non-objects
merge ( { prop : 'a' } , { prop : { } } ) // returns {prop: {}}
merge-anything dengan benar menjaga objek khusus tetap utuh seperti tanggal, regex, fungsi, instance kelas, dll.
Namun, sangat penting bagi Anda untuk memahami cara mengatasi referensi objek JavaScript. Pastikan untuk membaca #catatan tentang referensi objek JavaScript di bawah.
Perilaku defaultnya adalah array ditimpa. Anda dapat mengimpor mergeAndConcat
jika Anda perlu menggabungkan array. Namun jangan khawatir jika Anda tidak memerlukannya, perpustakaan ini dapat digoncangkan dan tidak akan mengimpor kode yang tidak Anda gunakan!
import { mergeAndConcat } from 'merge-anything'
mergeAndConcat (
{ nested : { prop : { array : [ 'a' ] } } } ,
{ nested : { prop : { array : [ 'b' ] } } }
)
// returns { nested: { prop: { array: ['a', 'b'] } } },
Mungkin ada saatnya Anda perlu mengubah logika ketika dua hal digabungkan. Anda dapat menyediakan fungsi kustom Anda sendiri yang dipicu setiap kali suatu nilai ditimpa.
Untuk kasus ini kami menggunakan mergeAndCompare
. Berikut adalah contoh fungsi perbandingan yang menggabungkan string:
import { mergeAndCompare } from 'merge-anything'
function concatStrings ( originVal , newVal , key ) {
if ( typeof originVal === 'string' && typeof newVal === 'string' ) {
// concat logic
return ` ${ originVal } ${ newVal } `
}
// always return newVal as fallback!!
return newVal
}
mergeAndCompare ( concatStrings , { name : 'John' } , { name : 'Simth' } )
// returns { name: 'JohnSmith' }
Catatan untuk pengguna TypeScript. Tipe yang dikembalikan oleh fungsi ini mungkin salah. Dalam hal ini Anda harus melemparkan hasilnya ke antarmuka yang Anda sediakan
Hati-hati dengan referensi objek JavaScript. Properti apa pun yang disarangkan akan bersifat reaktif dan tertaut antara objek asli dan objek yang digabungkan! Di bawah ini kami akan menunjukkan cara mencegahnya.
const original = { airport : { status : 'dep. ?' } }
const extraInfo = { airport : { location : 'Brussels' } }
const merged = merge ( original , extraInfo )
// we change the status from departuring ? to landing ?
merged . airport . status = 'lan. ?'
// the `merged` value will be modified
// merged.airport.status === 'lan. ?'
// However `original` value will also be modified!!
// original.airport.status === 'lan. ?'
Aturan utama yang perlu diingat adalah:
Properti apa pun yang bertingkat lebih dari 1 tingkat tanpa properti induk yang tumpang tindih akan bersifat reaktif dan ditautkan dalam hasil penggabungan dan sumbernya
Namun sebenarnya ada solusi yang sangat mudah . Kita cukup menyalin hasil penggabungan untuk menghilangkan reaktivitas apa pun. Untuk ini kita bisa menggunakan perpustakaan copy-apa saja. Perpustakaan ini juga memastikan bahwa instance kelas khusus tidak rusak , sehingga Anda dapat menggunakannya tanpa takut merusak barang!
Lihat di bawah bagaimana kami mengintegrasikan 'salin apa saja':
import { copy } from 'copy-anything'
const original = { airport : { status : 'dep. ?' } }
const extraInfo = { airport : { location : 'Brussels' } }
const merged = copy ( merge ( original , extraInfo ) )
// we change the status from departuring ? to landing ?
merged . airport . status = 'lan. ?' ( merged . airport . status === 'lan. ?' ) (
// true
// `original` won't be modified!
original . airport . status === 'dep. ?'
) // true
Anda kemudian dapat bermain-main di mana Anda ingin menempatkan fungsi copy()
.
Salin Apa Pun juga didukung sepenuhnya oleh TypeScript!
Ini secara harfiah hanya menelusuri suatu objek secara rekursif dan memberikan nilai ke objek baru seperti di bawah ini. Namun, itu dibungkus untuk memungkinkan parameter tambahan dll. Kode di bawah ini adalah integrasi dasar, yang akan membuat Anda memahami dasar-dasar cara kerjanya.
import { isPlainObject } from 'is-what'
function mergeRecursively ( origin , newComer ) {
if ( ! isPlainObject ( newComer ) ) return newComer
// define newObject to merge all values upon
const newObject = isPlainObject ( origin )
? Object . keys ( origin ) . reduce ( ( carry , key ) => {
const targetVal = origin [ key ]
if ( ! Object . keys ( newComer ) . includes ( key ) ) carry [ key ] = targetVal
return carry
} , { } )
: { }
return Object . keys ( newComer ) . reduce ( ( carry , key ) => {
const newVal = newComer [ key ]
const targetVal = origin [ key ]
// early return when targetVal === undefined
if ( targetVal === undefined ) {
carry [ key ] = newVal
return carry
}
// When newVal is an object do the merge recursively
if ( isPlainObject ( newVal ) ) {
carry [ key ] = mergeRecursively ( targetVal , newVal )
return carry
}
// all the rest
carry [ key ] = newVal
return carry
} , newObject )
}
* Tentu saja, ada perbedaan kecil dengan kode sumber sebenarnya untuk mengatasi kasus yang jarang terjadi & fitur tambahan. Kode sumber sebenarnya ada di sini.