ฉันจะลบคุณลักษณะทั้งหมดที่อยู่undefinedหรือnullในวัตถุ JavaScript ได้อย่างไร
(คำถามคล้ายกับคำถามนี้สำหรับอาร์เรย์)
ฉันจะลบคุณลักษณะทั้งหมดที่อยู่undefinedหรือnullในวัตถุ JavaScript ได้อย่างไร
(คำถามคล้ายกับคำถามนี้สำหรับอาร์เรย์)
คำตอบ:
คุณสามารถวนซ้ำวัตถุ:
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);
หากคุณกังวลเกี่ยวกับการลบคุณสมบัตินี้ที่ไม่ได้ทำงานในห่วงโซ่ proptype ของวัตถุคุณสามารถ:
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];
}
}
}
หมายเหตุเล็กน้อยเกี่ยวกับ null และไม่ได้กำหนด:
test.test1 === null; // true
test.test1 == null; // true
test.notaprop === null; // false
test.notaprop == null; // true
test.notaprop === undefined; // true
test.notaprop == undefined; // true
ใช้ES6 / ES2015บางอย่าง:
1) ง่ายหนึ่งซับเพื่อลบรายการแบบอินไลน์โดยไม่ได้รับมอบหมาย:
Object.keys(myObj).forEach((key) => (myObj[key] == null) && delete myObj[key]);
2) ตัวอย่างนี้ถูกลบ ...
3) ตัวอย่างแรกเขียนเป็นฟังก์ชัน:
const removeEmpty = obj => {
Object.keys(obj).forEach(key => obj[key] == null && delete obj[key]);
};
4) ฟังก์ชั่นนี้ใช้การเรียกซ้ำเพื่อลบรายการออกจากวัตถุที่ซ้อนกันเช่นกัน:
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) สิ่งนี้คล้ายกับ 4) แต่แทนที่จะกลายพันธุ์วัตถุต้นทางโดยตรงจะส่งคืนวัตถุใหม่
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) การทำงานวิธีการที่ 4b) ตาม@ คำตอบ MichaelJ.Zoidl ของใช้และfilter() reduce()อันนี้ส่งคืนวัตถุใหม่เช่นกัน:
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) เช่นเดียวกับ 4) แต่มีES7 / Object.entries()2016
const removeEmpty = (obj) =>
Object.entries(obj).forEach(([key, val]) => {
if (val && typeof val === 'object') removeEmpty(val)
else if (val == null) delete obj[key]
})
5b)
เวอร์ชันการทำงานอื่นที่ใช้การเรียกซ้ำและส่งคืนวัตถุใหม่ด้วย 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) เหมือนกับ 4) แต่ในES5ธรรมดา:
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]
});
};
keysจากobjectดังนั้นoและkที่เห็นได้ชัด แต่ฉันคิดว่ามันเป็นเรื่องของรสนิยม
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; }, {})
หากคุณใช้ lodash หรือ underscore.js ต่อไปนี้เป็นวิธีแก้ไขปัญหาที่ง่าย:
var obj = {name: 'John', age: null};
var compacted = _.pickBy(obj);
สิ่งนี้จะใช้ได้กับ lodash 4, pre lodash 4 หรือ underscore.js ใช้งาน_.pick(obj, _.identity)เท่านั้น
_.omit(obj, _.isUndefined)ก็ดีกว่า
_.isUndefinedไม่ละเว้นค่า null ใช้_.omitBy(obj, _.isNil)เพื่อละเว้นทั้งคู่undefinedและnull
สั้นที่สุดหนึ่ง liners สำหรับ ES6 +
กรองค่า falsy ทั้งหมด ( "", 0, false, null, undefined)
Object.entries(obj).reduce((a,[k,v]) => (v ? (a[k]=v, a) : a), {})
ตัวกรองnullและundefinedค่า:
Object.entries(obj).reduce((a,[k,v]) => (v == null ? a : (a[k]=v, a)), {})
กรองเท่านั้น null
Object.entries(obj).reduce((a,[k,v]) => (v === null ? a : (a[k]=v, a)), {})
กรองเท่านั้น undefined
Object.entries(obj).reduce((a,[k,v]) => (v === undefined ? a : (a[k]=v, a)), {})
โซลูชันแบบเรียกซ้ำ:ตัวกรองnullและundefined
สำหรับวัตถุ:
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)), {});
สำหรับวัตถุและอาร์เรย์:
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 == nullคุณจะตรวจสอบกับและundefined null
cleanEmptyโซลูชั่น recursve จะกลับวัตถุว่างเปล่า{}สำหรับวัตถุวัน
หากใครต้องการคำตอบของ Owen (และ Eric's) แบบเรียกซ้ำนี่คือ:
/**
* 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);
}
}
}
hasOwnPropertyใช้if(test.hasOwnProperty(i)) { ... }
JSON.stringify ลบคีย์ที่ไม่ได้กำหนด
removeUndefined = function(json){
return JSON.parse(JSON.stringify(json))
}
nullได้รับการปฏิบัติเหมือนundefinedใช้ฟังก์ชั่นการเปลี่ยนสำหรับข้อมูลเพิ่มเติมอ้างถึงคำตอบนี้: stackoverflow.com/questions/286141/…
nullค่า ลองดู: แล้วlet a = { b: 1, c: 0, d: false, e: null, f: undefined, g: [], h: {} } console.log(removeUndefined(a))คำถามเกี่ยวกับundefinedและnullคุณค่า
โซลูชัน Lodash ที่เป็นไปได้ง่ายที่สุดในการส่งคืนวัตถุด้วยค่าnullและundefinedค่าที่กรองออก
_.omitBy(obj, _.isNil)
คุณสามารถใช้การรวมกันของJSON.stringifyพารามิเตอร์ replacer และJSON.parseเพื่อเปลี่ยนกลับเป็นวัตถุ การใช้วิธีนี้ยังหมายถึงการแทนที่จะทำกับคีย์ที่ซ้อนกันทั้งหมดภายในวัตถุที่ซ้อนกัน
ตัวอย่างวัตถุ
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]
}
]
};
ฟังก์ชั่นทดแทน
function replaceUndefinedOrNull(key, value) {
if (value === null || value === undefined) {
return undefined;
}
return value;
}
ทำความสะอาดวัตถุ
exampleObject = JSON.stringify(exampleObject, replaceUndefinedOrNull);
exampleObject = JSON.parse(exampleObject);
ใช้ramda # pickByคุณจะลบทั้งหมดnull, undefinedและfalseค่า:
const obj = {a:1, b: undefined, c: null, d: 1}
R.pickBy(R.identity, obj)
ดังที่ @ manroe ชี้ให้เห็นว่าเพื่อให้falseคุณค่าใช้isNil():
const obj = {a:1, b: undefined, c: null, d: 1, e: false}
R.pickBy(v => !R.isNil(v), obj)
(v) => !R.isNil(v)อาจเป็นทางเลือกที่ดีกว่าสำหรับคำถามของ OP เนื่องจากfalseค่าหรือความผิดพลาดอื่น ๆ จะถูกปฏิเสธโดยR.identity
วิธีการใช้งานและไม่เปลี่ยนรูปแบบโดย.filterไม่ต้องสร้างวัตถุเกินความจำเป็น
Object.keys(obj).reduce((acc, key) => (obj[key] === undefined ? acc : {...acc, [key]: obj[key]}), {})
obj[key] === undefinedเป็นobj[key] === undefined || obj[key] === null
const omitFalsy = obj => Object.keys(obj).reduce((acc, key) => ({ ...acc, ...(obj[key] && { [key]: obj[key] }) }), {});
คุณสามารถทำการลบซ้ำในหนึ่งบรรทัดโดยใช้อาร์กิวเมนต์ replacer ของ json.stringify
const removeNullValues = obj => (
JSON.parse(JSON.stringify(obj, (k,v) => v ?? undefined))
)
การใช้งาน:
removeNullValues({a:{x:1,y:null,z:undefined}}) // Returns {a:{x:1}}
ดังที่ได้กล่าวไว้ในความคิดเห็นของ Emmanuel เทคนิคนี้ใช้งานได้เฉพาะในกรณีที่โครงสร้างข้อมูลของคุณมีเฉพาะประเภทข้อมูลที่สามารถใส่ในรูปแบบ JSON (สตริงตัวเลขรายการ ฯลฯ )
(คำตอบนี้ได้รับการปรับปรุงใหม่ใช้ประกอบการ Nullish หลอมรวมขึ้นอยู่กับความต้องการการสนับสนุนเบราว์เซอร์ที่คุณอาจต้องการที่จะใช้ฟังก์ชั่นนี้แทน:. (k,v) => v!=null ? v : undefined)
NaNเพื่อnullที่จะไม่ถูกลบ
คุณสามารถทำได้สั้นลงโดยมี!เงื่อนไข
var r = {a: null, b: undefined, c:1};
for(var k in r)
if(!r[k]) delete r[k];
โปรดจำไว้ว่าในการใช้งาน: เป็น @semicolor ประกาศในความคิดเห็น: นี่จะลบคุณสมบัติหากค่าเป็นสตริงว่างเปล่า, เท็จหรือศูนย์
[null, undefined].includes(r[k]) !r[k]
โซลูชันที่สั้นกว่า ES6 บริสุทธิ์แปลงเป็นอาร์เรย์ใช้ฟังก์ชันตัวกรองและแปลงกลับเป็นวัตถุ จะเป็นเรื่องง่ายที่จะสร้างฟังก์ชั่น ...
Btw ด้วยสิ่งนี้.length > 0ฉันตรวจสอบว่ามีสตริง / อาเรย์ที่ว่างเปล่าดังนั้นมันจะลบคีย์ว่าง
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; }, {});
nullและมันจะง่ายต่อการใช้งานเพียงแค่undefined MY_OBJECT[f] != nullโซลูชันปัจจุบันของคุณจะลบทุกอย่าง แต่ไม่ใช่สตริง / รายการที่ว่างเปล่าและเกิดข้อผิดพลาดเมื่อค่าคือnull
filterได้ซึ่งจะสามารถอ่านได้มากขึ้น
omitทำคุณต้องตรวจสอบ obj ก่อนที่จะโทรObject.keys:const omit = (obj, filter) => obj && Object.keys(obj).filter(key => !filter(obj[key])).reduce((acc,key) => {acc[key] = obj[key]; return acc}, {});
หากคุณต้องการโซลูชัน ES7 4 สาย:
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;
หรือถ้าคุณชอบเวอร์ชั่นที่อ่านง่ายกว่า:
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;
}
สิ่งนี้จะรักษาค่าบูลีนและจะทำความสะอาดอาร์เรย์ด้วย นอกจากนี้ยังรักษาวัตถุต้นฉบับด้วยการส่งคืนสำเนาที่ทำความสะอาด
ฉันมีสถานการณ์เดียวกันในโครงการของฉันและประสบความสำเร็จโดยใช้วิธีการต่อไปนี้
สามารถใช้งานได้กับทุกประเภทข้อมูลที่กล่าวมาข้างต้นไม่สามารถใช้งานกับวันที่และอาร์เรย์ที่ว่างเปล่า
removeEmptyKeysFromObject.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;
}
ผ่านวัตถุใด ๆ ไปยังฟังก์ชั่นนี้ removeEmptyKeysFromObject ()
สำหรับการค้นหาอย่างลึกซึ้งฉันใช้รหัสต่อไปนี้อาจจะมีประโยชน์สำหรับทุกคนที่ดูคำถามนี้ (มันไม่สามารถใช้งานได้สำหรับการอ้างอิงแบบวนซ้ำ)
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;
}
หากคุณไม่ต้องการที่จะกลายพันธุ์ในสถานที่ แต่กลับโคลนด้วยการลบโมฆะ / ไม่ได้กำหนดคุณสามารถใช้ฟังก์ชั่นลด 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;
}, {});
}
แทนที่จะลบคุณสมบัติคุณสามารถสร้างวัตถุใหม่ด้วยปุ่มที่ไม่เป็นโมฆะ
const removeEmpty = (obj) => {
return Object.keys(obj).filter(key => obj[key]).reduce(
(newObj, key) => {
newObj[key] = obj[key]
return newObj
}, {}
)
}
เพื่อ piggypack ในคำตอบของเบนเกี่ยวกับวิธีการแก้ปัญหานี้โดยใช้ lodash ของ_.pickByคุณยังสามารถแก้ปัญหานี้ในห้องสมุดน้องสาว: Underscore.js_.pick 's
var obj = {name: 'John', age: null};
var compacted = _.pick(obj, function(value) {
return value !== null && value !== undefined;
});
ผู้ช่วยลดสามารถทำเคล็ดลับ (โดยไม่ต้องตรวจสอบประเภท) -
const cleanObj = Object.entries(objToClean).reduce((acc, [key, value]) => {
if (value) {
acc[key] = value;
}
return acc;
}, {});
หากมีคนต้องการลบundefinedค่าออกจากวัตถุที่มีการค้นหาลึกโดยใช้lodashนี่คือรหัสที่ฉันใช้ มันค่อนข้างง่ายในการปรับเปลี่ยนเพื่อลบค่าว่างทั้งหมด ( 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;
}, {});
}
ด้วย Lodash:
_.omitBy({a: 1, b: null}, (v) => !v)
หากคุณใช้ eslint และต้องการหลีกเลี่ยงการสะดุดกฎที่ไม่มีการกำหนดใหม่คุณสามารถใช้ Object.assign ร่วมกับ. reduce และชื่อคุณสมบัติที่คำนวณได้สำหรับโซลูชัน ES6 ที่สง่างามพอสมควร:
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 }
นี่คือวิธีการทำงานในการลบออกnullsจากวัตถุโดยใช้ ES6 โดยไม่ต้องปิดการใช้งานวัตถุโดยใช้เพียงreduce:
const stripNulls = (obj) => {
return Object.keys(obj).reduce((acc, current) => {
if (obj[current] !== null) {
return { ...acc, [current]: obj[current] }
}
return acc
}, {})
}
stripNullsฟังก์ชั่นจะใช้การอ้างอิงจากภายนอกขอบเขตของฟังก์ชันตัวสะสม และมันยังผสมความกังวลโดยการกรองภายในฟังก์ชันตัวสะสม 😝 (เช่นObject.entries(o).filter(([k,v]) => v !== null).reduce((o, [k, v]) => {o[k] = v; return o;}, {});) ใช่มันจะวนซ้ำรายการที่ถูกกรองสองครั้ง แต่การสูญเสีย perf ที่เกิดขึ้นจริงนั้นเล็กน้อยมาก
นอกจากนี้คุณยังสามารถใช้...ไวยากรณ์การแพร่กระจายโดยใช้forEachสิ่งนี้:
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)
เราสามารถใช้ JSON.stringify และ JSON.parse เพื่อลบแอตทริบิวต์ว่างจากวัตถุ
jsObject = JSON.parse(JSON.stringify(jsObject), (key, value) => {
if (value == null || value == '' || value == [] || value == {})
return undefined;
return value;
});
{} != {}และ[] != []) แต่วิธีการอื่นไม่ถูกต้อง
นี่คือฟังก์ชั่นแบบเรียกซ้ำที่ครอบคลุม (แต่เดิมมาจากฟังก์ชั่น @chickens) ที่จะ:
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
}
การใช้:
// 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]))
หากคุณต้องการวิธีการที่บริสุทธิ์ / ฟังก์ชั่น
const stripUndef = obj =>
Object.keys(obj)
.reduce((p, c) => ({ ...p, ...(x[c] === undefined ? { } : { [c]: x[c] })}), {});