Bagaimana cara menghapus semua atribut yang ada undefined atau nulldalam objek JavaScript?
(Pertanyaan serupa dengan yang ini untuk Array)
Bagaimana cara menghapus semua atribut yang ada undefined atau nulldalam objek JavaScript?
(Pertanyaan serupa dengan yang ini untuk Array)
Jawaban:
Anda dapat mengulangi objek:
var test = {
test1 : null,
test2 : 'somestring',
test3 : 3,
}
function clean(obj) {
for (var propName in obj) {
if (obj[propName] === null || obj[propName] === undefined) {
delete obj[propName];
}
}
}
clean(test);
Jika Anda khawatir tentang penghapusan properti ini yang tidak menjalankan rantai proptipe objek, Anda juga dapat:
function clean(obj) {
var propNames = Object.getOwnPropertyNames(obj);
for (var i = 0; i < propNames.length; i++) {
var propName = propNames[i];
if (obj[propName] === null || obj[propName] === undefined) {
delete obj[propName];
}
}
}
Beberapa catatan tentang nol vs tidak terdefinisi:
test.test1 === null; // true
test.test1 == null; // true
test.notaprop === null; // false
test.notaprop == null; // true
test.notaprop === undefined; // true
test.notaprop == undefined; // true
Menggunakan beberapa ES6 / ES2015 :
1) Satu kalimat sederhana untuk menghapus item sebaris tanpa tugas:
Object.keys(myObj).forEach((key) => (myObj[key] == null) && delete myObj[key]);
2) Contoh ini telah dihapus ...
3) Contoh pertama ditulis sebagai fungsi:
const removeEmpty = obj => {
Object.keys(obj).forEach(key => obj[key] == null && delete obj[key]);
};
4) Fungsi ini menggunakan rekursi untuk menghapus item dari objek bersarang juga:
const removeEmpty = obj => {
Object.keys(obj).forEach(key => {
if (obj[key] && typeof obj[key] === "object") removeEmpty(obj[key]); // recurse
else if (obj[key] == null) delete obj[key]; // delete
});
};
4b) Ini mirip dengan 4), tetapi alih-alih memutasikan objek sumber secara langsung, ia mengembalikan objek baru.
const removeEmpty = obj => {
const newObj = {};
Object.keys(obj).forEach(key => {
if (obj[key] && typeof obj[key] === "object") {
newObj[key] = removeEmpty(obj[key]); // recurse
} else if (obj[key] != null) {
newObj[key] = obj[key]; // copy value
}
});
return newObj;
};
5) Pendekatan fungsional untuk 4b) berdasarkan jawaban @ MichaelJ.Zoidl menggunakan filter()dan reduce(). Ini juga mengembalikan objek baru:
const removeEmpty = obj =>
Object.keys(obj)
.filter(k => obj[k] != null) // Remove undef. and null.
.reduce(
(newObj, k) =>
typeof obj[k] === "object"
? { ...newObj, [k]: removeEmpty(obj[k]) } // Recurse.
: { ...newObj, [k]: obj[k] }, // Copy value.
{}
);
6) Sama seperti 4) tetapi dengan ES7 / 2016 Object.entries() .
const removeEmpty = (obj) =>
Object.entries(obj).forEach(([key, val]) => {
if (val && typeof val === 'object') removeEmpty(val)
else if (val == null) delete obj[key]
})
5b)
Versi fungsional lain yang menggunakan rekursi dan mengembalikan objek baru dengan ES2019 Object.fromEntries() :
const removeEmpty = obj =>
Object.fromEntries(
Object.entries(obj)
.filter(([k, v]) => v != null)
.map(([k, v]) => (typeof v === "object" ? [k, removeEmpty(v)] : [k, v]))
);
7) Sama seperti 4) tetapi dalam ES5 polos :
function removeEmpty(obj) {
Object.keys(obj).forEach(function(key) {
if (obj[key] && typeof obj[key] === 'object') removeEmpty(obj[key])
else if (obj[key] == null) delete obj[key]
});
};
keysdari object, jadi odan kjelas. Tapi saya rasa ini masalah selera.
Object.keys(myObj).forEach(function (key) {(myObj[key] == null) && delete myObj[key]});
Object.entries(myObj).reduce((acc, [key, val]) => { if (val) acc[key] = val; return acc; }, {})
Jika Anda menggunakan lodash atau underscore.js, berikut adalah solusi sederhana:
var obj = {name: 'John', age: null};
var compacted = _.pickBy(obj);
Ini hanya akan bekerja dengan lodash 4, pre lodash 4 atau underscore.js, gunakan _.pick(obj, _.identity);
_.omit(obj, _.isUndefined)lebih baik.
_.isUndefinedtidak menghilangkan nulls, gunakan _.omitBy(obj, _.isNil)untuk menghilangkan keduanya undefineddannull
Satu liner terpendek untuk ES6 +
Menyaring semua nilai falsy ( "", 0, false, null, undefined)
Object.entries(obj).reduce((a,[k,v]) => (v ? (a[k]=v, a) : a), {})
Filter nulldan undefinednilai:
Object.entries(obj).reduce((a,[k,v]) => (v == null ? a : (a[k]=v, a)), {})
Saringan HANYA null
Object.entries(obj).reduce((a,[k,v]) => (v === null ? a : (a[k]=v, a)), {})
Saringan HANYA undefined
Object.entries(obj).reduce((a,[k,v]) => (v === undefined ? a : (a[k]=v, a)), {})
Solusi Rekursif: Filter nulldanundefined
Untuk Objek:
const cleanEmpty = obj => Object.entries(obj)
.map(([k,v])=>[k,v && typeof v === "object" ? cleanEmpty(v) : v])
.reduce((a,[k,v]) => (v == null ? a : (a[k]=v, a)), {});
Untuk Objek dan Array:
const cleanEmpty = obj => {
if (Array.isArray(obj)) {
return obj
.map(v => (v && typeof v === 'object') ? cleanEmpty(v) : v)
.filter(v => !(v == null));
} else {
return Object.entries(obj)
.map(([k, v]) => [k, v && typeof v === 'object' ? cleanEmpty(v) : v])
.reduce((a, [k, v]) => (v == null ? a : (a[k]=v, a)), {});
}
}
v == nullAnda akan memeriksa undefineddan null.
cleanEmptysolusi recursve akan kembali objek yang kosong {}untuk Tanggal benda
Jika seseorang membutuhkan versi rekursif dari jawaban Owen (dan Eric), ini dia:
/**
* Delete all null (or undefined) properties from an object.
* Set 'recurse' to true if you also want to delete properties in nested objects.
*/
function delete_null_properties(test, recurse) {
for (var i in test) {
if (test[i] === null) {
delete test[i];
} else if (recurse && typeof test[i] === 'object') {
delete_null_properties(test[i], recurse);
}
}
}
hasOwnPropertymenggunakanif(test.hasOwnProperty(i)) { ... }
JSON.stringify menghapus kunci yang tidak ditentukan.
removeUndefined = function(json){
return JSON.parse(JSON.stringify(json))
}
nulldiperlakukan sebagai undefinedmenggunakan fungsi penggantian, untuk info lebih lanjut lihat jawaban ini: stackoverflow.com/questions/286141/…
nullnilai. Coba: let a = { b: 1, c: 0, d: false, e: null, f: undefined, g: [], h: {} }lalu console.log(removeUndefined(a)). Pertanyaan tentang undefineddan nullnilai - nilai.
Anda dapat menggunakan kombinasi JSON.stringifyparameter replacer-nya, dan JSON.parsemengubahnya kembali menjadi objek. Menggunakan metode ini juga berarti penggantian dilakukan untuk semua kunci bersarang di dalam objek bersarang.
Contoh Obyek
var exampleObject = {
string: 'value',
emptyString: '',
integer: 0,
nullValue: null,
array: [1, 2, 3],
object: {
string: 'value',
emptyString: '',
integer: 0,
nullValue: null,
array: [1, 2, 3]
},
arrayOfObjects: [
{
string: 'value',
emptyString: '',
integer: 0,
nullValue: null,
array: [1, 2, 3]
},
{
string: 'value',
emptyString: '',
integer: 0,
nullValue: null,
array: [1, 2, 3]
}
]
};
Fungsi Pengganti
function replaceUndefinedOrNull(key, value) {
if (value === null || value === undefined) {
return undefined;
}
return value;
}
Bersihkan Obyek
exampleObject = JSON.stringify(exampleObject, replaceUndefinedOrNull);
exampleObject = JSON.parse(exampleObject);
Menggunakan ramda # pickBy Anda akan menghapus semua null, undefineddan falsenilainya:
const obj = {a:1, b: undefined, c: null, d: 1}
R.pickBy(R.identity, obj)
Seperti yang ditunjukkan @manroe, untuk menjaga agar falsenilai tetap digunakan isNil():
const obj = {a:1, b: undefined, c: null, d: 1, e: false}
R.pickBy(v => !R.isNil(v), obj)
(v) => !R.isNil(v)mungkin merupakan pilihan yang lebih baik untuk pertanyaan OP, mengingat bahwa falseatau nilai-nilai palsu lainnya juga akan ditolak olehR.identity
Pendekatan fungsional dan abadi, tanpa .filterdan tanpa menciptakan lebih banyak objek dari yang dibutuhkan
Object.keys(obj).reduce((acc, key) => (obj[key] === undefined ? acc : {...acc, [key]: obj[key]}), {})
obj[key] === undefinedkeobj[key] === undefined || obj[key] === null
const omitFalsy = obj => Object.keys(obj).reduce((acc, key) => ({ ...acc, ...(obj[key] && { [key]: obj[key] }) }), {});
Anda dapat melakukan penghapusan rekursif dalam satu baris menggunakan argumen replacer json.stringify
const removeEmptyValues = obj => (
JSON.parse(JSON.stringify(obj, (k,v) => v ?? undefined))
)
Pemakaian:
removeEmptyValues({a:{x:1,y:null,z:undefined}}) // Returns {a:{x:1}}
Seperti disebutkan dalam komentar Emmanuel, teknik ini hanya berfungsi jika struktur data Anda hanya berisi tipe data yang dapat dimasukkan ke dalam format JSON (string, angka, daftar, dll).
(Jawaban ini telah diperbarui untuk menggunakan baru Operator Nullish penggabungan tergantung pada kebutuhan dukungan browser Anda mungkin ingin menggunakan fungsi ini sebagai gantinya:. (k,v) => v!=null ? v : undefined)
NaNke objek nullyang tidak dihapus.
Anda dapat melakukan lebih pendek dengan !kondisi
var r = {a: null, b: undefined, c:1};
for(var k in r)
if(!r[k]) delete r[k];
Ingat dalam penggunaan: seperti yang diumumkan @semicolor dalam komentar: Ini juga akan menghapus properti jika nilainya berupa string kosong, false atau nol
[null, undefined].includes(r[k])sebagai ganti !r[k].
Solusi murni ES6 yang lebih pendek, mengubahnya menjadi array, menggunakan fungsi filter dan mengubahnya kembali ke objek. Juga mudah membuat fungsi ...
Btw. dengan ini .length > 0saya periksa apakah ada string / array kosong, sehingga akan menghapus kunci kosong.
const MY_OBJECT = { f: 'te', a: [] }
Object.keys(MY_OBJECT)
.filter(f => !!MY_OBJECT[f] && MY_OBJECT[f].length > 0)
.reduce((r, i) => { r[i] = MY_OBJECT[i]; return r; }, {});
nulldan undefinedakan lebih mudah untuk digunakan MY_OBJECT[f] != null. Solusi Anda saat ini menghilangkan semuanya kecuali string kosong / daftar dan melempar kesalahan saat nilainyanull
filter, akan lebih mudah dibaca.
omit, Anda perlu memeriksa obj yang ada sebelum memanggil Object.keys:const omit = (obj, filter) => obj && Object.keys(obj).filter(key => !filter(obj[key])).reduce((acc,key) => {acc[key] = obj[key]; return acc}, {});
Jika Anda menginginkan 4 baris solusi ES7 murni:
const clean = e => e instanceof Object ? Object.entries(e).reduce((o, [k, v]) => {
if (typeof v === 'boolean' || v) o[k] = clean(v);
return o;
}, e instanceof Array ? [] : {}) : e;
Atau jika Anda lebih suka versi yang lebih mudah dibaca:
function filterEmpty(obj, [key, val]) {
if (typeof val === 'boolean' || val) {
obj[key] = clean(val)
};
return obj;
}
function clean(entry) {
if (entry instanceof Object) {
const type = entry instanceof Array ? [] : {};
const entries = Object.entries(entry);
return entries.reduce(filterEmpty, type);
}
return entry;
}
Ini akan mempertahankan nilai boolean dan akan membersihkan array juga. Ini juga mempertahankan objek asli dengan mengembalikan salinan yang sudah dibersihkan.
Saya memiliki skenario yang sama dalam proyek saya dan dicapai dengan menggunakan metode berikut.
Ini bekerja dengan semua tipe data, beberapa yang disebutkan di atas tidak bekerja dengan array tanggal dan kosong.
hapusEmptyKeysFromObject.js
removeEmptyKeysFromObject(obj) {
Object.keys(obj).forEach(key => {
if (Object.prototype.toString.call(obj[key]) === '[object Date]' && (obj[key].toString().length === 0 || obj[key].toString() === 'Invalid Date')) {
delete obj[key];
} else if (obj[key] && typeof obj[key] === 'object') {
this.removeEmptyKeysFromObject(obj[key]);
} else if (obj[key] == null || obj[key] === '') {
delete obj[key];
}
if (obj[key]
&& typeof obj[key] === 'object'
&& Object.keys(obj[key]).length === 0
&& Object.prototype.toString.call(obj[key]) !== '[object Date]') {
delete obj[key];
}
});
return obj;
}
meneruskan objek apa pun ke fungsi ini removeEmptyKeysFromObject ()
Untuk pencarian mendalam saya menggunakan kode berikut, mungkin ini akan berguna bagi siapa pun yang melihat pertanyaan ini (tidak dapat digunakan untuk dependensi siklik):
function removeEmptyValues(obj) {
for (var propName in obj) {
if (!obj[propName] || obj[propName].length === 0) {
delete obj[propName];
} else if (typeof obj[propName] === 'object') {
removeEmptyValues(obj[propName]);
}
}
return obj;
}
Jika Anda tidak ingin bermutasi di tempat, tetapi mengembalikan klon dengan null / undefined dihapus, Anda bisa menggunakan fungsi pengurangan ES6.
// Helper to remove undefined or null properties from an object
function removeEmpty(obj) {
// Protect against null/undefined object passed in
return Object.keys(obj || {}).reduce((x, k) => {
// Check for null or undefined
if (obj[k] != null) {
x[k] = obj[k];
}
return x;
}, {});
}
Untuk piggypack pada jawaban Ben tentang cara untuk memecahkan masalah ini dengan menggunakan lodash ini _.pickBy, Anda juga dapat memecahkan masalah ini di adik perpustakaan: Underscore.js 's _.pick.
var obj = {name: 'John', age: null};
var compacted = _.pick(obj, function(value) {
return value !== null && value !== undefined;
});
Lihat: Contoh JSFiddle
Jika seseorang perlu menghapus undefinednilai dari suatu objek dengan pencarian mendalam menggunakan lodashmaka di sini adalah kode yang saya gunakan. Cukup mudah untuk memodifikasinya untuk menghapus semua nilai kosong ( null/ undefined).
function omitUndefinedDeep(obj) {
return _.reduce(obj, function(result, value, key) {
if (_.isObject(value)) {
result[key] = omitUndefinedDeep(value);
}
else if (!_.isUndefined(value)) {
result[key] = value;
}
return result;
}, {});
}
Dengan Lodash:
_.omitBy({a: 1, b: null}, (v) => !v)
Jika Anda menggunakan eslint dan ingin menghindari melanggar aturan no-param-reassign, Anda dapat menggunakan Object.assign bersama dengan .reduce dan nama properti yang dihitung untuk solusi ES6 yang cukup elegan:
const queryParams = { a: 'a', b: 'b', c: 'c', d: undefined, e: null, f: '', g: 0 };
const cleanParams = Object.keys(queryParams)
.filter(key => queryParams[key] != null)
.reduce((acc, key) => Object.assign(acc, { [key]: queryParams[key] }), {});
// { a: 'a', b: 'b', c: 'c', f: '', g: 0 }
Berikut adalah cara fungsional untuk menghapus nullsdari Obyek menggunakan ES6 tanpa bermutasi objek hanya menggunakan reduce:
const stripNulls = (obj) => {
return Object.keys(obj).reduce((acc, current) => {
if (obj[current] !== null) {
return { ...acc, [current]: obj[current] }
}
return acc
}, {})
}
stripNullsfungsi itu menggunakan referensi dari luar ruang lingkup fungsi akumulator; dan itu juga mencampur kekhawatiran dengan memfilter dalam fungsi akumulator. 😝 (mis. Object.entries(o).filter(([k,v]) => v !== null).reduce((o, [k, v]) => {o[k] = v; return o;}, {});) Ya, itu akan mengulang item yang disaring dua kali tetapi kerugian yang disadari di sana dapat diabaikan.
Anda juga dapat menggunakan ...sintaks spread menggunakan forEachsesuatu seperti ini:
let obj = { a: 1, b: "b", c: undefined, d: null };
let cleanObj = {};
Object.keys(obj).forEach(val => {
const newVal = obj[val];
cleanObj = newVal ? { ...cleanObj, [val]: newVal } : cleanObj;
});
console.info(cleanObj);
// General cleanObj function
const cleanObj = (valsToRemoveArr, obj) => {
Object.keys(obj).forEach( (key) =>
if (valsToRemoveArr.includes(obj[key])){
delete obj[key]
}
})
}
cleanObj([undefined, null], obj)
const getObjWithoutVals = (dontReturnValsArr, obj) => {
const cleanObj = {}
Object.entries(obj).forEach( ([key, val]) => {
if(!dontReturnValsArr.includes(val)){
cleanObj[key]= val
}
})
return cleanObj
}
//To get a new object without `null` or `undefined` run:
const nonEmptyObj = getObjWithoutVals([undefined, null], obj)
Kita bisa menggunakan JSON.stringify dan JSON.parse untuk menghapus atribut kosong dari suatu objek.
jsObject = JSON.parse(JSON.stringify(jsObject), (key, value) => {
if (value == null || value == '' || value == [] || value == {})
return undefined;
return value;
});
{} != {}dan [] != []), tetapi sebaliknya pendekatan valid
Berikut adalah fungsi rekursif yang komprehensif (awalnya didasarkan pada yang oleh @chickens) yang akan:
defaults=[undefined, null, '', NaN]const cleanEmpty = function(obj, defaults = [undefined, null, NaN, '']) {
if (!defaults.length) return obj
if (defaults.includes(obj)) return
if (Array.isArray(obj))
return obj
.map(v => v && typeof v === 'object' ? cleanEmpty(v, defaults) : v)
.filter(v => !defaults.includes(v))
return Object.entries(obj).length
? Object.entries(obj)
.map(([k, v]) => ([k, v && typeof v === 'object' ? cleanEmpty(v, defaults) : v]))
.reduce((a, [k, v]) => (defaults.includes(v) ? a : { ...a, [k]: v}), {})
: obj
}
PEMAKAIAN:
// based off the recursive cleanEmpty function by @chickens.
// This one can also handle Date objects correctly
// and has a defaults list for values you want stripped.
const cleanEmpty = function(obj, defaults = [undefined, null, NaN, '']) {
if (!defaults.length) return obj
if (defaults.includes(obj)) return
if (Array.isArray(obj))
return obj
.map(v => v && typeof v === 'object' ? cleanEmpty(v, defaults) : v)
.filter(v => !defaults.includes(v))
return Object.entries(obj).length
? Object.entries(obj)
.map(([k, v]) => ([k, v && typeof v === 'object' ? cleanEmpty(v, defaults) : v]))
.reduce((a, [k, v]) => (defaults.includes(v) ? a : { ...a, [k]: v}), {})
: obj
}
// testing
console.log('testing: undefined \n', cleanEmpty(undefined))
console.log('testing: null \n',cleanEmpty(null))
console.log('testing: NaN \n',cleanEmpty(NaN))
console.log('testing: empty string \n',cleanEmpty(''))
console.log('testing: empty array \n',cleanEmpty([]))
console.log('testing: date object \n',cleanEmpty(new Date(1589339052 * 1000)))
console.log('testing: nested empty arr \n',cleanEmpty({ 1: { 2 :null, 3: [] }}))
console.log('testing: comprehensive obj \n', cleanEmpty({
a: 5,
b: 0,
c: undefined,
d: {
e: null,
f: [{
a: undefined,
b: new Date(),
c: ''
}]
},
g: NaN,
h: null
}))
console.log('testing: different defaults \n', cleanEmpty({
a: 5,
b: 0,
c: undefined,
d: {
e: null,
f: [{
a: undefined,
b: '',
c: new Date()
}]
},
g: [0, 1, 2, 3, 4],
h: '',
}, [undefined, null]))
Jika Anda lebih suka pendekatan murni / fungsional
const stripUndef = obj =>
Object.keys(obj)
.reduce((p, c) => ({ ...p, ...(x[c] === undefined ? { } : { [c]: x[c] })}), {});