Xóa các thuộc tính trống khỏi một đối tượng trong Javascript


266

Làm cách nào để xóa tất cả các thuộc tính đang undefinedhoặc nulltrong một đối tượng JavaScript?

(Câu hỏi tương tự như câu hỏi này cho Mảng)


19
Rất khuyến khích mọi người bỏ qua thứ hạng hàng đầu và chuyển sang các phiên bản ES6 / ES7 tại đây, stackoverflow.com/a/38340730/124486
Evan Carroll

2
Ngoài ra ES6 một lớp lót mà không có đối tượng đột biến ở đây: stackoverflow.com/a/57625661/1602301

Câu trả lời:


184

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

2
Đã thêm một sự điều chỉnh nhanh chóng. Biến "i" không được khai báo sẽ rò rỉ ra phạm vi bên ngoài nếu đoạn mã này từng được sử dụng trong một hàm.
Eric Nguyễn

4
bạn có thể đơn giản hóa (test [i] === null || test [i] === không xác định) thành (test [i] == null)
jaf0

Xin chào, @EricNguyen, không giống như C và một số ngôn ngữ khác, javascript không có phạm vi khối cho các biến (chỉ phạm vi chức năng), do đó, biến i sẽ luôn rò rỉ vào phạm vi sau khối for .
Gerardo Lima

1
@GerardoLima, vâng. Tôi đã giả định rằng tất cả điều này sẽ được bao bọc trong một chức năng. Ý tôi là (giả sử tất cả được bao bọc bởi một hàm) là bạn cần khai báo var hoặc tôi sẽ rò rỉ ngay cả ngoài phạm vi hàm.
Eric Nguyễn

Điều này cũng sẽ lặp qua nguyên mẫu của đối tượng nguyên thủy - điều mà trong hầu hết các trường hợp là không mong muốn. stackoverflow.com/a/2869372/1612318
Rotareti

427

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]);

jsbin

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]);
};

jsbin

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
  });
};

jsbin

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()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.
      {}
    );

jsbin

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]
  });
};

jsbin


3
@AugustinRiedinger Khi tôi phải quyết định giữa ngắt dòng và viết tắt, đôi khi tôi viết tắt nếu tôi nghĩ rằng viết tắt là xấu xa hơn. Mã trong 5) không khó để lý giải và đó là một hàm loại bỏ trống keyskhỏi một object, vì vậy okrõ ràng. Nhưng tôi đoán đó là vấn đề của hương vị.
Rotareti

3
Phiên bản đầu tiên với hương vị ES5:Object.keys(myObj).forEach(function (key) {(myObj[key] == null) && delete myObj[key]});
Chất dẫn truyền thần kinh

1
Một dòng, không có chức năng:Object.entries(myObj).reduce((acc, [key, val]) => { if (val) acc[key] = val; return acc; }, {})
Paul Slm

7
Vì chúng tôi đang cố gắng kỹ lưỡng, có thể rất tốt khi thấy một giải pháp bất biến. Đây là những đột biến đối tượng nguồn và đang trả lại một cách giả dối đối tượng thực sự không cần thiết vì đối tượng đã bị đột biến. Người mới bắt đầu sẽ nắm bắt giá trị đối tượng trả về và tự hỏi tại sao đối tượng nguồn của họ cũng bị sửa đổi.
Mike McLin

2
5) Không hoạt động với mảng (Object.keys sẽ trả về số vị trí mảng làm khóa cho các phần tử). Có thể những người khác gặp vấn đề này, nhưng tôi đã tìm thấy điều này khi thử nghiệm 5.
Eelco

95

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) ;


1
Xuất sắc! Cảm ơn bạn! FYI, điều không rõ ràng với tôi là bạn có thể sử dụng nó như thế này: foo (). Then (_. PickBy); // lọc ra kết quả trống
Maciej Gurban

29
Lưu ý rằng điều này sẽ không có kết quả mong muốn nếu đối tượng chứa các giá trị sai lệch như 0 hoặc chuỗi rỗng. Sau đó _.omit(obj, _.isUndefined)thì tốt hơn.
JHH

5
@JHH _.isUndefinedkhông bỏ sót null, sử dụng _.omitBy(obj, _.isNil)để bỏ qua cả hai undefinednull
Lukasz Wiktor

@LukaszWiktor Đúng, câu hỏi đã hỏi không xác định hoặc null.
JHH

88

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 nullundefinedgiá 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 nullundefined

Đố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)), {});
  } 
}

10
Đây nên là câu trả lời duy nhất! Mỗi đoạn mã này sẽ tạo ra một đối tượng mới trong đó đối tượng cũ sẽ không bị đột biến. Điều này là thích hợp hơn! Một lưu ý nhỏ nếu bạn chỉ sử dụng v == nullbạn sẽ kiểm tra lại undefinednull.
Megajin

các cleanEmptygiải pháp đệ quy sẽ trả về một đối tượng trống {}cho các đối tượng Date
Emmanuel NK

Một chút dễ đọc hơn trong một lớp lót sẽ khiến chúng trở nên tuyệt vời !!
zardilior

39

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);
        }
    }
}

Sau khi vòng lặp for bắt đầu, bạn nên kiểm tra xem đối tượng có hasOwnPropertysử dụng khôngif(test.hasOwnProperty(i)) { ... }
Augie Gardner

@AugieGardner Tôi tò mò tại sao bạn muốn kiểm tra điều này - vui lòng giải thích nếu bạn muốn. (Nó có ngăn cản việc kiểm tra các tài sản được thừa kế không?)
Wumms

24

JSON.opesify loại bỏ các khóa không xác định.

removeUndefined = function(json){
  return JSON.parse(JSON.stringify(json))
}

Điều này không làm việc cho tôi cho một đối tượng sâu sắc, nhưng câu trả lời của Wumm ở trên đã làm.
Suman

1
Nếu bạn cần nullđược coi là undefinedsử 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/
Lỗi

Chỉ cần lưu ý điều này không loại bỏ nullcá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ề undefinednullgiá trị.
mayid

13

Bạn có thể đang tìm kiếm deletetừ khóa.

var obj = { };
obj.theProperty = 1;
delete obj.theProperty;

4
Đây là những gì anh ta đang làm ở trên, điều này cũng vẫn không xác định trong đối tượng.
Josh Bedo

10

Giải pháp Lodash đơn giản nhất có thể để trả về một đối tượng với các giá trị nullundefinedđược lọc ra.

_.omitBy(obj, _.isNil)


Đây là giải pháp sạch nhất cho đến nay!
Jee Mok

9

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);

Ví dụ CodePen


6

Sử dụng ramda # pickBy bạn sẽ loại bỏ tất cả null, undefinedfalsegiá trị:

const obj = {a:1, b: undefined, c: null, d: 1}
R.pickBy(R.identity, obj)

Như @manroe đã chỉ ra, để giữ falsegiá trị sử dụng isNil():

const obj = {a:1, b: undefined, c: null, d: 1, e: false}
R.pickBy(v => !R.isNil(v), obj)

1
(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 falsehoặc các giá trị R.identity
giả mạo

6

Phương pháp tiếp cận chức năng và bất biến, không có .filtervà 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]}), {})

Câu trả lời rất súc tích. Để thêm kiểm tra null, chỉ cần thay thế obj[key] === undefinedvàoobj[key] === undefined || obj[key] === null
user3658510

một thay đổi nhỏ của cách tiếp cận ở trên: bạn cũng có thể lan truyền một cách có điều kiện trong tài sản obj trung thực như vậyconst omitFalsy = obj => Object.keys(obj).reduce((acc, key) => ({ ...acc, ...(obj[key] && { [key]: obj[key] }) }), {});
Kevin K.

6

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:)


1
điều này sẽ chuyển đổi các đối tượng Date thành chuỗi, chuyển đổi NaNthành nullkhông bị loại bỏ.
Emmanuel NK

5

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


11
Đ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 bằng không.
Dấu chấm phẩy

3
Đây chính xác là những gì tôi đang tìm kiếm để loại bỏ các trường không mong muốn khỏi một yêu cầu JSON. Cảm ơn!
Ph Frozen

Sử dụng [null, undefined].includes(r[k])thay vì !r[k].
selmansamet

5

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 > 0tô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; }, {});

Mã BIN https://jsbin.com/kugoyinora/edit?js,console


1
Giải pháp chức năng tuyệt vời
puiu

Tôi thích điều này! Nhưng tôi nghĩ để loại bỏ tất cả nullundefinednó 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
Rotareti

Đúng vậy, bạn cũng có thể sử dụng / chuỗi nhiều filter', sẽ dễ đọc hơn.
Michael J. Zoidl

Nếu bạn khái quát điều này một chút, tôi nghĩ rằng bạn đã tiến gần đến những gì loadash đang omitlà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}, {});
icc97

Đẹp, nhưng bất kỳ giá trị số nguyên sẽ được loại bỏ với phương pháp này.
Ghis

4

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.


4

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 ()


4

Đố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;
    }

3

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;
  }, {});
}

3

Thay vì xóa thuộc tính, bạn cũng có thể tạo một đối tượng mới với các khóa không phải là null.

const removeEmpty = (obj) => {
  return Object.keys(obj).filter(key => obj[key]).reduce(
    (newObj, key) => {
      newObj[key] = obj[key]
      return newObj
    }, {}
  )
}

3

Để 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


1
Điều này trả về mảng trống, bạn cũng đã thay đổi tên của obj thành đối tượng
Stephen DuMont

Cảm ơn bạn Stephen! Làm thế nào bây giờ? Tôi đã cập nhật câu trả lời của mình để bao gồm một liên kết JSFiddle.
Alex Johnson

thử sử dụng _.omit (obj, _.isEmpty); đây là khái niệm thuần túy hơn và sẽ bao gồm chuỗi rỗng.
Stephen DuMont

3

một người trợ giúp giảm có thể thực hiện thủ thuật (không cần kiểm tra kiểu) -

const cleanObj = Object.entries(objToClean).reduce((acc, [key, value]) => {
      if (value) {
        acc[key] = value;
      }
      return acc;
    }, {});

2

Nếu ai đó cần xóa undefinedcác giá trị khỏi một đối tượng có tìm kiếm sâu bằng cách sử dụng lodashthì đâ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;
  }, {});
}


1

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 }

1

Đây là một cách chức năng để loại bỏ nullskhỏ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
  }, {})
}

Nhận xét về Troll Hai điều liên quan đến việc đây là một mẫu chức năng: trong stripNullschứ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ể.
Jason Cust

1

Bạn cũng có thể sử dụng ...cú pháp lây lan bằng cách sử dụng forEachmộ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);

1

Làm sạch đồ vật tại chỗ

// General cleanObj function
const cleanObj = (valsToRemoveArr, obj) => {
   Object.keys(obj).forEach( (key) =>
      if (valsToRemoveArr.includes(obj[key])){
         delete obj[key]
      }
   })
}

cleanObj([undefined, null], obj)

Chức năng tinh khiết

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)

Đây là một giải pháp tốt, có thể là một lớp lót
thiệu lại vào

1

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;
           });

Thủ thuật này thực sự hợp lệ, miễn là bạn đảm bảo rằng Obj có khả năng tuần tự hóa JSON. Và nó hoạt động sâu sắc là tốt.
Polv

So sánh mảng và đối tượng không hợp lệ ( {} != {}[] != []), nhưng cách tiếp cận khác là hợp lệ
Aivara

1

Đây là một hàm đệ quy toàn diện (ban đầu dựa trên hàm của @chickens) sẽ:

  • đệ quy loại bỏ những gì bạn nói với nó defaults=[undefined, null, '', NaN]
  • Xử lý chính xác các đối tượng thông thường, mảng và đối tượng Date
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]))


0

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] })}), {});
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.