ลบแอตทริบิวต์ที่ว่างเปล่าออกจาก Object ใน Javascript


266

ฉันจะลบคุณลักษณะทั้งหมดที่อยู่undefinedหรือnullในวัตถุ JavaScript ได้อย่างไร

(คำถามคล้ายกับคำถามนี้สำหรับอาร์เรย์)


19
ขอแนะนำอย่างยิ่งให้ผู้คนไม่สนใจอันดับต้น ๆ และย้ายไปที่ ES6 / ES7 เวอร์ชั่นที่นี่stackoverflow.com/a/38340730/124486
Evan Carroll

2
นอกจากนี้ยังมี ES6 หนึ่ง liners โดยไม่ต้องกลายพันธุ์วัตถุอยู่ที่นี่: stackoverflow.com/a/57625661/1602301
ไก่

คำตอบ:


184

คุณสามารถวนซ้ำวัตถุ:

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

2
เพิ่มการแก้ไขอย่างรวดเร็ว ตัวแปร "i" ที่ไม่ได้ประกาศจะรั่วไหลออกไปนอกขอบเขตหากตัวอย่างข้อมูลนี้เคยถูกใช้ในฟังก์ชั่น
Eric Nguyen

4
คุณสามารถทำให้ (test [i] === null || test [i] === ไม่ได้กำหนด) เป็น (test [i] == null)
jaf0

สวัสดี @EricNguyen ซึ่งแตกต่างจาก C และอีกหลายภาษาอื่น ๆ จาวาสคริปต์ไม่ได้มีขอบเขตบล็อกสำหรับตัวแปร (ขอบเขตฟังก์ชั่นเท่านั้น) ดังนั้นตัวแปรฉันมักจะรั่วไหลเข้าไปในขอบเขตหลังสำหรับบล็อก
Gerardo Lima

1
@ GerardoLima ใช่ ฉันคิดว่านี่จะเป็นหน้าที่ทั้งหมด สิ่งที่ฉันหมายถึง (สมมติว่าสิ่งนี้ห่อด้วยฟังก์ชั่นทั้งหมด) คือคุณต้องการประกาศ var หรือฉันจะรั่วไหลแม้นอกขอบเขตฟังก์ชั่น
Eric Nguyen

สิ่งนี้จะวนซ้ำผ่านต้นแบบของวัตถุดั้งเดิมซึ่งในกรณีส่วนใหญ่ไม่ต้องการ stackoverflow.com/a/2869372/1612318
Rotareti

427

ใช้ES6 / ES2015บางอย่าง:

1) ง่ายหนึ่งซับเพื่อลบรายการแบบอินไลน์โดยไม่ได้รับมอบหมาย:

Object.keys(myObj).forEach((key) => (myObj[key] == null) && delete myObj[key]);

jsbin

2) ตัวอย่างนี้ถูกลบ ...

3) ตัวอย่างแรกเขียนเป็นฟังก์ชัน:

const removeEmpty = obj => {
  Object.keys(obj).forEach(key => obj[key] == null && delete obj[key]);
};

jsbin

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

jsbin

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

jsbin

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

jsbin


3
@AugustinRiedinger เมื่อฉันต้องตัดสินใจระหว่างตัวแบ่งบรรทัดและตัวย่อบางครั้งฉันไปหาตัวย่อถ้าฉันคิดว่าตัวย่อเป็นความชั่วร้ายที่น้อยกว่า รหัสใน 5) ไม่ได้เป็นเรื่องยากที่จะเกี่ยวกับเหตุผลและเป็นฟังก์ชั่นที่เอาที่ว่างเปล่าkeysจากobjectดังนั้นoและkที่เห็นได้ชัด แต่ฉันคิดว่ามันเป็นเรื่องของรสนิยม
Rotareti

3
รุ่นแรกที่มีรสชาติ ES5:Object.keys(myObj).forEach(function (key) {(myObj[key] == null) && delete myObj[key]});
สารสื่อประสาท

1
หนึ่งบรรทัดโดยไม่มีฟังก์ชั่น:Object.entries(myObj).reduce((acc, [key, val]) => { if (val) acc[key] = val; return acc; }, {})
Paul Slm

7
เนื่องจากเรากำลังพยายามอย่างละเอียดถี่ถ้วนจึงอาจเป็นเรื่องดีที่จะเห็นทางออกที่ไม่เปลี่ยนรูป สิ่งเหล่านี้กำลังกลายพันธุ์วัตถุต้นฉบับและหลอกลวงคืนวัตถุซึ่งไม่จำเป็นจริง ๆ เนื่องจากวัตถุนั้นกลายพันธุ์ ผู้เริ่มต้นจะจับมูลค่าวัตถุที่ส่งคืนและสงสัยว่าทำไมวัตถุต้นฉบับของพวกเขาจะถูกแก้ไขด้วย
Mike McLin

2
5) ไม่ทำงานกับอาร์เรย์ (Object.keys จะส่งกลับหมายเลขตำแหน่งอาเรย์เป็นกุญแจสำคัญสำหรับองค์ประกอบ) อาจเป็นไปได้ว่าคนอื่นมีปัญหานี้ แต่ฉันพบสิ่งนี้เมื่อทำการทดสอบ 5
Eelco

95

หากคุณใช้ lodash หรือ underscore.js ต่อไปนี้เป็นวิธีแก้ไขปัญหาที่ง่าย:

var obj = {name: 'John', age: null};

var compacted = _.pickBy(obj);

สิ่งนี้จะใช้ได้กับ lodash 4, pre lodash 4 หรือ underscore.js ใช้งาน_.pick(obj, _.identity)เท่านั้น


1
ยอดเยี่ยม! ขอบคุณ! FYI สิ่งที่ไม่ชัดเจนสำหรับฉันคือคุณสามารถใช้มันเช่นนี้: foo (). ดังนั้น (_. pickBy); // กรองผลลัพธ์ที่ว่างเปล่า
Maciej Gurban

29
โปรดทราบว่าสิ่งนี้จะไม่มีผลลัพธ์ที่ต้องการหากวัตถุมีค่าเท็จเช่น 0 หรือสตริงว่าง ถ้าอย่างนั้น_.omit(obj, _.isUndefined)ก็ดีกว่า
JHH

5
@JHH _.isUndefinedไม่ละเว้นค่า null ใช้_.omitBy(obj, _.isNil)เพื่อละเว้นทั้งคู่undefinedและnull
Lukasz Wiktor

@LukaszWiktor ถูกต้องคำถามที่ถามไม่ได้กำหนดหรือโมฆะ
JHH

86

สั้นที่สุดหนึ่ง 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)), {});
  } 
}

10
นี่ควรเป็นคำตอบเดียว! ตัวอย่างข้อมูลเหล่านี้แต่ละรายการจะสร้างวัตถุใหม่ที่จะไม่กลายพันธุ์วัตถุเก่า นี้เป็นที่นิยมกว่า! บันทึกเล็ก ๆ น้อย ๆ ถ้าคุณเพียงแค่ใช้v == nullคุณจะตรวจสอบกับและundefined null
Megajin

cleanEmptyโซลูชั่น recursve จะกลับวัตถุว่างเปล่า{}สำหรับวัตถุวัน
เอ็มมานู NK

ความชัดเจนมากขึ้นใน liners หนึ่งจะทำให้พวกเขาน่ากลัว !!
zardilior

39

หากใครต้องการคำตอบของ 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);
        }
    }
}

หลังจากวนรอบ for เริ่มขึ้นคุณควรตรวจสอบว่าวัตถุที่hasOwnPropertyใช้if(test.hasOwnProperty(i)) { ... }
Augie Gardner

@AugieGardner ฉันอยากรู้ว่าทำไมคุณถึงต้องการตรวจสอบเรื่องนี้ - โปรดอธิบายหากคุณต้องการ (มันจะป้องกันการตรวจสอบคุณสมบัติที่สืบทอดมาหรือไม่)
Wumms

24

JSON.stringify ลบคีย์ที่ไม่ได้กำหนด

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

สิ่งนี้ไม่ได้ผลสำหรับฉันสำหรับวัตถุลึก แต่คำตอบของ Wumm ด้านบนทำได้
Suman

1
หากคุณจำเป็นต้องnullได้รับการปฏิบัติเหมือนundefinedใช้ฟังก์ชั่นการเปลี่ยนสำหรับข้อมูลเพิ่มเติมอ้างถึงคำตอบนี้: stackoverflow.com/questions/286141/…
Hooman Askari

เพิ่งทราบว่านี่ไม่ได้ลบnullค่า ลองดู: แล้วlet a = { b: 1, c: 0, d: false, e: null, f: undefined, g: [], h: {} } console.log(removeUndefined(a))คำถามเกี่ยวกับundefinedและnullคุณค่า
mayid

13

คุณอาจกำลังมองหาdeleteคำหลัก

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

4
นี่คือสิ่งที่เขากำลังทำอยู่ด้านบนสิ่งนี้ยังคงทิ้งคำจำกัดความไว้ในวัตถุ
Josh Bedo

10

โซลูชัน Lodash ที่เป็นไปได้ง่ายที่สุดในการส่งคืนวัตถุด้วยค่าnullและundefinedค่าที่กรองออก

_.omitBy(obj, _.isNil)


นี่คือทางออกที่สะอาดที่สุด!
Jee Mok

9

คุณสามารถใช้การรวมกันของ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);

ตัวอย่าง CodePen


6

ใช้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)

1
(v) => !R.isNil(v)อาจเป็นทางเลือกที่ดีกว่าสำหรับคำถามของ OP เนื่องจากfalseค่าหรือความผิดพลาดอื่น ๆ จะถูกปฏิเสธโดยR.identity
manroe

6

วิธีการใช้งานและไม่เปลี่ยนรูปแบบโดย.filterไม่ต้องสร้างวัตถุเกินความจำเป็น

Object.keys(obj).reduce((acc, key) => (obj[key] === undefined ? acc : {...acc, [key]: obj[key]}), {})

คำตอบที่กระชับมาก หากต้องการเพิ่มการตรวจสอบค่า Null เพียงเปลี่ยนobj[key] === undefinedเป็นobj[key] === undefined || obj[key] === null
user3658510

รูปแบบที่แตกต่างกันเล็กน้อยของวิธีการข้างต้น: คุณยังสามารถแพร่กระจายอย่างมีเงื่อนไขในคุณสมบัติ obj ความจริงเช่นนั้นconst omitFalsy = obj => Object.keys(obj).reduce((acc, key) => ({ ...acc, ...(obj[key] && { [key]: obj[key] }) }), {});
เควินเค

6

คุณสามารถทำการลบซ้ำในหนึ่งบรรทัดโดยใช้อาร์กิวเมนต์ 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)


1
นี้จะแปลงวัตถุวันสตริง, แปลงNaNเพื่อnullที่จะไม่ถูกลบ
Emmanuel NK

5

คุณสามารถทำได้สั้นลงโดยมี!เงื่อนไข

var r = {a: null, b: undefined, c:1};
for(var k in r)
   if(!r[k]) delete r[k];

โปรดจำไว้ว่าในการใช้งาน: เป็น @semicolor ประกาศในความคิดเห็น: นี่จะลบคุณสมบัติหากค่าเป็นสตริงว่างเปล่า, เท็จหรือศูนย์


11
สิ่งนี้จะลบคุณสมบัติหากค่าเป็นสตริงว่างเปล่าเท็จหรือเป็นศูนย์
Semicolon

3
นี่คือสิ่งที่ฉันต้องการเพื่อลบเขตข้อมูลที่ไม่ต้องการออกจากคำขอ JSON ขอบคุณ!
Phrozen

ใช้แทน[null, undefined].includes(r[k]) !r[k]
selmansamet

5

โซลูชันที่สั้นกว่า 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; }, {});

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


1
วิธีแก้ปัญหาการใช้งานที่ดี
puiu

ฉันชอบสิ่งนี้! แต่ผมคิดว่าการลบทั้งหมดnullและมันจะง่ายต่อการใช้งานเพียงแค่undefined MY_OBJECT[f] != nullโซลูชันปัจจุบันของคุณจะลบทุกอย่าง แต่ไม่ใช่สตริง / รายการที่ว่างเปล่าและเกิดข้อผิดพลาดเมื่อค่าคือnull
Rotareti

ขวาคุณยังสามารถใช้ / เชื่อมต่อหลายรายการfilterได้ซึ่งจะสามารถอ่านได้มากขึ้น
Michael J. Zoidl

ถ้าคุณพูดแบบนี้เล็กน้อยฉันคิดว่าคุณเข้าใกล้สิ่งที่ loadash 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}, {});
icc97

ดี แต่ค่าจำนวนเต็มใด ๆ จะถูกลบด้วยวิธีนี้
Ghis

4

หากคุณต้องการโซลูชัน 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;
}

สิ่งนี้จะรักษาค่าบูลีนและจะทำความสะอาดอาร์เรย์ด้วย นอกจากนี้ยังรักษาวัตถุต้นฉบับด้วยการส่งคืนสำเนาที่ทำความสะอาด


4

ฉันมีสถานการณ์เดียวกันในโครงการของฉันและประสบความสำเร็จโดยใช้วิธีการต่อไปนี้

สามารถใช้งานได้กับทุกประเภทข้อมูลที่กล่าวมาข้างต้นไม่สามารถใช้งานกับวันที่และอาร์เรย์ที่ว่างเปล่า

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


4

สำหรับการค้นหาอย่างลึกซึ้งฉันใช้รหัสต่อไปนี้อาจจะมีประโยชน์สำหรับทุกคนที่ดูคำถามนี้ (มันไม่สามารถใช้งานได้สำหรับการอ้างอิงแบบวนซ้ำ)

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

หากคุณไม่ต้องการที่จะกลายพันธุ์ในสถานที่ แต่กลับโคลนด้วยการลบโมฆะ / ไม่ได้กำหนดคุณสามารถใช้ฟังก์ชั่นลด 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

แทนที่จะลบคุณสมบัติคุณสามารถสร้างวัตถุใหม่ด้วยปุ่มที่ไม่เป็นโมฆะ

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

3

เพื่อ piggypack ในคำตอบของเบนเกี่ยวกับวิธีการแก้ปัญหานี้โดยใช้ lodash ของ_.pickByคุณยังสามารถแก้ปัญหานี้ในห้องสมุดน้องสาว: Underscore.js_.pick 's

var obj = {name: 'John', age: null};

var compacted = _.pick(obj, function(value) {
  return value !== null && value !== undefined;
});

ดู: ตัวอย่าง JSFiddle


1
สิ่งนี้จะส่งคืนอาเรย์ที่ว่างเปล่าและคุณเปลี่ยนชื่อของ obj เป็น object
Stephen DuMont

ขอบคุณสตีเฟ่น! แล้วตอนนี้ล่ะ? ฉันได้อัปเดตคำตอบเพื่อรวมลิงก์ JSFiddle แล้ว
Alex Johnson

ลองใช้ _.omit (obj, _.isEmpty); นี่คือแนวคิดที่บริสุทธิ์มากขึ้นและจะมีสตริงว่าง
Stephen DuMont

3

ผู้ช่วยลดสามารถทำเคล็ดลับ (โดยไม่ต้องตรวจสอบประเภท) -

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

2

หากมีคนต้องการลบ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;
  }, {});
}


1

หากคุณใช้ 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 }

1

นี่คือวิธีการทำงานในการลบออกnullsจากวัตถุโดยใช้ ES6 โดยไม่ต้องปิดการใช้งานวัตถุโดยใช้เพียงreduce:

const stripNulls = (obj) => {
  return Object.keys(obj).reduce((acc, current) => {
    if (obj[current] !== null) {
      return { ...acc, [current]: obj[current] }
    }
    return acc
  }, {})
}

Troll commentสองสิ่งที่เกี่ยวกับสิ่งนี้คือรูปแบบการใช้งาน: ภายในstripNullsฟังก์ชั่นจะใช้การอ้างอิงจากภายนอกขอบเขตของฟังก์ชันตัวสะสม และมันยังผสมความกังวลโดยการกรองภายในฟังก์ชันตัวสะสม 😝 (เช่นObject.entries(o).filter(([k,v]) => v !== null).reduce((o, [k, v]) => {o[k] = v; return o;}, {});) ใช่มันจะวนซ้ำรายการที่ถูกกรองสองครั้ง แต่การสูญเสีย perf ที่เกิดขึ้นจริงนั้นเล็กน้อยมาก
Jason Cust

1

นอกจากนี้คุณยังสามารถใช้...ไวยากรณ์การแพร่กระจายโดยใช้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);

1

วัตถุที่สะอาดอยู่ในที่

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

อันนี้เป็นคำตอบที่ดีน่าจะเป็นคำตอบ
rekam

1

เราสามารถใช้ JSON.stringify และ JSON.parse เพื่อลบแอตทริบิวต์ว่างจากวัตถุ

jsObject = JSON.parse(JSON.stringify(jsObject), (key, value) => {
               if (value == null || value == '' || value == [] || value == {})
                   return undefined;
               return value;
           });

เคล็ดลับนี้ใช้งานได้จริงตราบใดที่คุณมั่นใจว่า Obj นั้นเป็นอนุกรม JSON และก็ทำงานได้ลึกเช่นกัน
Polv

การเปรียบเทียบอาร์เรย์และวัตถุไม่ถูกต้อง ( {} != {}และ[] != []) แต่วิธีการอื่นไม่ถูกต้อง
Aivaras

1

นี่คือฟังก์ชั่นแบบเรียกซ้ำที่ครอบคลุม (แต่เดิมมาจากฟังก์ชั่น @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]))


0

หากคุณต้องการวิธีการที่บริสุทธิ์ / ฟังก์ชั่น

const stripUndef = obj => 
  Object.keys(obj)
   .reduce((p, c) => ({ ...p, ...(x[c] === undefined ? { } : { [c]: x[c] })}), {});
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.