Làm cách nào để xóa tất cả các thuộc tính đang undefined
hoặc null
trong một đối tượng JavaScript?
(Câu hỏi tương tự như câu hỏi này cho Mảng)
Làm cách nào để xóa tất cả các thuộc tính đang undefined
hoặc null
trong một đối tượng JavaScript?
(Câu hỏi tương tự như câu hỏi này cho Mảng)
Câu trả lời:
Bạn có thể lặp qua đối tượng:
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);
Nếu bạn lo ngại về việc loại bỏ thuộc tính này không chạy chuỗi proptype của đối tượng, bạn cũng có thể:
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];
}
}
}
Một vài lưu ý về null vs không xác định:
test.test1 === null; // true
test.test1 == null; // true
test.notaprop === null; // false
test.notaprop == null; // true
test.notaprop === undefined; // true
test.notaprop == undefined; // true
Sử dụng một số ES6 / ES2015 :
1) Một lớp lót đơn giản để loại bỏ các mục nội tuyến mà không cần gán:
Object.keys(myObj).forEach((key) => (myObj[key] == null) && delete myObj[key]);
2) Ví dụ này đã bị xóa ...
3) Ví dụ đầu tiên được viết dưới dạng hàm:
const removeEmpty = obj => {
Object.keys(obj).forEach(key => obj[key] == null && delete obj[key]);
};
4) Hàm này cũng sử dụng đệ quy để xóa các mục khỏi các đối tượng lồng nhau:
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) Điều này tương tự với 4), nhưng thay vì trực tiếp biến đổi đối tượng nguồn, nó trả về một đối tượng mới.
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) Cách tiếp cận chức năng với 4b) dựa trên câu trả lời của @ MichaelJ.Zoidl bằng cách sử dụng filter()
và reduce()
. Cái này cũng trả về một đối tượng mới:
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) Tương tự như 4) nhưng với 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) Một
phiên bản chức năng khác sử dụng đệ quy và trả về một đối tượng mới với 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) Tương tự như 4) nhưng trong ES5 đơn giản :
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
khỏi một object
, vì vậy o
và k
rõ ràng. Nhưng tôi đoán đó là vấn đề của hương vị.
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; }, {})
Nếu bạn đang sử dụng lodash hoặc underscore.js, đây là một giải pháp đơn giản:
var obj = {name: 'John', age: null};
var compacted = _.pickBy(obj);
Điều này sẽ chỉ hoạt động với lodash 4, pre lodash 4 hoặc underscore.js, sử dụng _.pick(obj, _.identity)
;
_.omit(obj, _.isUndefined)
thì tốt hơn.
_.isUndefined
không bỏ sót null, sử dụng _.omitBy(obj, _.isNil)
để bỏ qua cả hai undefined
vànull
Một lớp lót ngắn nhất cho ES6 +
Lọc tất cả các giá trị falsy ( ""
, 0
, false
, null
, undefined
)
Object.entries(obj).reduce((a,[k,v]) => (v ? (a[k]=v, a) : a), {})
Bộ lọc null
và undefined
giá trị:
Object.entries(obj).reduce((a,[k,v]) => (v == null ? a : (a[k]=v, a)), {})
Bộ lọc CHỈ null
Object.entries(obj).reduce((a,[k,v]) => (v === null ? a : (a[k]=v, a)), {})
Bộ lọc CHỈ undefined
Object.entries(obj).reduce((a,[k,v]) => (v === undefined ? a : (a[k]=v, a)), {})
Giải pháp đệ quy: Bộ lọc null
vàundefined
Đối với đối tượng:
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)), {});
Đối với các đối tượng và mảng:
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
bạn sẽ kiểm tra lại undefined
và null
.
cleanEmpty
giải pháp đệ quy sẽ trả về một đối tượng trống {}
cho các đối tượng Date
Nếu ai đó cần một phiên bản đệ quy của câu trả lời của Owen (và Eric), thì đây là:
/**
* 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
sử dụng khôngif(test.hasOwnProperty(i)) { ... }
JSON.opesify loại bỏ các khóa không xác định.
removeUndefined = function(json){
return JSON.parse(JSON.stringify(json))
}
null
được coi là undefined
sử dụng chức năng thay thế, để biết thêm thông tin, hãy tham khảo câu trả lời này: stackoverflow.com/questions/286141/
null
các giá trị. Hãy thử: let a = { b: 1, c: 0, d: false, e: null, f: undefined, g: [], h: {} }
và sau đó console.log(removeUndefined(a))
. Câu hỏi là về undefined
và null
giá trị.
Bạn có thể sử dụng kết hợp JSON.stringify
, tham số thay thế của nó vàJSON.parse
để biến nó trở lại thành một đối tượng. Sử dụng phương pháp này cũng có nghĩa là việc thay thế được thực hiện cho tất cả các khóa được lồng trong các đối tượng lồng nhau.
Đối tượng ví dụ
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]
}
]
};
Chức năng thay thế
function replaceUndefinedOrNull(key, value) {
if (value === null || value === undefined) {
return undefined;
}
return value;
}
Làm sạch đối tượng
exampleObject = JSON.stringify(exampleObject, replaceUndefinedOrNull);
exampleObject = JSON.parse(exampleObject);
Sử dụng ramda # pickBy bạn sẽ loại bỏ tất cả null
, undefined
và false
giá trị:
const obj = {a:1, b: undefined, c: null, d: 1}
R.pickBy(R.identity, obj)
Như @manroe đã chỉ ra, để giữ false
giá trị sử dụng isNil()
:
const obj = {a:1, b: undefined, c: null, d: 1, e: false}
R.pickBy(v => !R.isNil(v), obj)
(v) => !R.isNil(v)
có lẽ là một lựa chọn tốt hơn cho câu hỏi của OP, vì rằng false
hoặc các giá trị R.identity
Phương pháp tiếp cận chức năng và bất biến, không có .filter
và không tạo ra nhiều đối tượng hơn mức cần thiết
Object.keys(obj).reduce((acc, key) => (obj[key] === undefined ? acc : {...acc, [key]: obj[key]}), {})
obj[key] === undefined
vàoobj[key] === undefined || obj[key] === null
const omitFalsy = obj => Object.keys(obj).reduce((acc, key) => ({ ...acc, ...(obj[key] && { [key]: obj[key] }) }), {});
Bạn có thể thực hiện xóa đệ quy trong một dòng bằng cách sử dụng đối số thay thế của json.opesify
const removeEmptyValues = obj => (
JSON.parse(JSON.stringify(obj, (k,v) => v ?? undefined))
)
Sử dụng:
removeEmptyValues({a:{x:1,y:null,z:undefined}}) // Returns {a:{x:1}}
Như đã đề cập trong nhận xét của Emmanuel, kỹ thuật này chỉ hoạt động nếu cấu trúc dữ liệu của bạn chỉ chứa các loại dữ liệu có thể được đặt ở định dạng JSON (chuỗi, số, danh sách, v.v.).
(Câu trả lời này đã được cập nhật để sử dụng toán tử Nullish Coalescing mới . Tùy thuộc vào nhu cầu hỗ trợ của trình duyệt, bạn có thể muốn sử dụng chức năng này thay thế (k,v) => v!=null ? v : undefined
:)
NaN
thành null
không bị loại bỏ.
bạn có thể làm ngắn hơn với !
điều kiện
var r = {a: null, b: undefined, c:1};
for(var k in r)
if(!r[k]) delete r[k];
Ghi nhớ trong cách sử dụng: như @semiaolor thông báo trong các bình luận: Điều này cũng sẽ xóa các thuộc tính nếu giá trị là một chuỗi rỗng, sai hoặc không
[null, undefined].includes(r[k])
thay vì !r[k]
.
Giải pháp thuần túy ES6 ngắn hơn, chuyển đổi nó thành một mảng, sử dụng chức năng lọc và chuyển đổi nó trở lại thành một đối tượng. Cũng có thể dễ dàng thực hiện một chức năng ...
Btw. với điều này .length > 0
tôi kiểm tra nếu có một chuỗi / mảng trống, vì vậy nó sẽ loại bỏ các khóa trống.
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
và undefined
nó sẽ đơn giản hơn để sử dụng MY_OBJECT[f] != null
. Giải pháp hiện tại của bạn sẽ xóa tất cả mọi thứ trừ các chuỗi / danh sách không trống và đưa ra lỗi khi các giá trị lànull
filter
', sẽ dễ đọc hơn.
omit
làm, bạn cần phải kiểm tra obj tồn tại trước khi gọi Object.keys
:const omit = (obj, filter) => obj && Object.keys(obj).filter(key => !filter(obj[key])).reduce((acc,key) => {acc[key] = obj[key]; return acc}, {});
Nếu bạn muốn 4 dòng của một giải pháp ES7 thuần túy:
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;
Hoặc nếu bạn thích phiên bản dễ đọc hơn:
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;
}
Điều này sẽ bảo tồn các giá trị boolean và nó cũng sẽ làm sạch các mảng. Nó cũng bảo tồn các đối tượng ban đầu bằng cách trả lại một bản sao được làm sạch.
Tôi có cùng kịch bản trong dự án của mình và đạt được bằng phương pháp sau.
Nó hoạt động với tất cả các loại dữ liệu, một số ít được đề cập ở trên không hoạt động với các mảng ngày và trống.
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;
}
truyền bất kỳ đối tượng nào cho hàm này removeEmptyKeysFromObject ()
Đối với một tìm kiếm sâu, tôi đã sử dụng đoạn mã sau, có thể nó sẽ hữu ích cho bất kỳ ai nhìn vào câu hỏi này (nó không thể sử dụng được cho các phụ thuộc theo chu kỳ):
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;
}
Nếu bạn không muốn đột biến tại chỗ, nhưng trả lại một bản sao với loại bỏ null / không xác định, bạn có thể sử dụng chức năng giảm 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;
}, {});
}
Để piggypack trên câu trả lời của Ben về cách giải quyết vấn đề này bằng lodash của _.pickBy
, bạn cũng có thể giải quyết vấn đề này trong thư viện chị: Underscore.js 's _.pick
.
var obj = {name: 'John', age: null};
var compacted = _.pick(obj, function(value) {
return value !== null && value !== undefined;
});
Xem: Ví dụ về JSFiddle
Nếu ai đó cần xóa undefined
các giá trị khỏi một đối tượng có tìm kiếm sâu bằng cách sử dụng lodash
thì đây là mã mà tôi đang sử dụng. Thật đơn giản để sửa đổi nó để loại bỏ tất cả các giá trị trống ( 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;
}, {});
}
Với Lodash:
_.omitBy({a: 1, b: null}, (v) => !v)
Nếu bạn sử dụng eslint và muốn tránh vấp phải quy tắc không xác định lại, bạn có thể sử dụng Object.assign kết hợp với .reduce và tên thuộc tính được tính toán cho giải pháp ES6 khá thanh lịch:
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 }
Đây là một cách chức năng để loại bỏ nulls
khỏi Object bằng ES6 mà không làm biến đổi đối tượng chỉ bằng cách sử dụng reduce
:
const stripNulls = (obj) => {
return Object.keys(obj).reduce((acc, current) => {
if (obj[current] !== null) {
return { ...acc, [current]: obj[current] }
}
return acc
}, {})
}
stripNulls
chức năng, nó sử dụng một tham chiếu từ bên ngoài phạm vi của hàm tích lũy; và nó cũng trộn lẫn các mối quan tâm bằng cách lọc trong hàm tích lũy. Eg (ví dụ Object.entries(o).filter(([k,v]) => v !== null).reduce((o, [k, v]) => {o[k] = v; return o;}, {});
) Có, nó sẽ lặp lại các mục được lọc hai lần nhưng tổn thất hoàn hảo nhận ra là không đáng kể.
Bạn cũng có thể sử dụng ...
cú pháp lây lan bằng cách sử dụng forEach
một cái gì đó như thế này:
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)
Chúng ta có thể sử dụng JSON.opesify và JSON.parse để xóa các thuộc tính trống khỏi một đối tượng.
jsObject = JSON.parse(JSON.stringify(jsObject), (key, value) => {
if (value == null || value == '' || value == [] || value == {})
return undefined;
return value;
});
{} != {}
và [] != []
), nhưng cách tiếp cận khác là hợp lệ
Đây là một hàm đệ quy toàn diện (ban đầu dựa trên hàm của @chickens) sẽ:
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
}
SỬ DỤNG:
// 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]))
Nếu bạn thích cách tiếp cận thuần túy / chức năng
const stripUndef = obj =>
Object.keys(obj)
.reduce((p, c) => ({ ...p, ...(x[c] === undefined ? { } : { [c]: x[c] })}), {});