检查空嵌套项的函数(包括数组、集合、字符串和映射)

Function to check empty nested items (including Arrays, Sets, Strings & Maps)

我正在尝试在 vanilla JS 中提出一个解决方案(不使用任何第三方库)来检查给定的输入并确定它是否 'empty'。

我有以下要匹配的代码和断言。 每个测试用例都有一个预期的答案作为评论。

我已经尝试了几个函数来 'deepCheck' 这些关于 stackblitz 的断言,但是 none 已经接近完全覆盖。

https://stackblitz.com/edit/node-ksxnjm

const assert = require('assert');



function isEmpty(obj) {
  return Object.keys(obj).every((k) => !Object.keys(obj[k]).length);
}

const test1 = {};                  // expect true
const test2 = { some: 'value' };   // expect false
const test3 = { some: {} };        // expect true
const test4 = [];                  // expect true
const test5 = [[]];                // expect true
const test6 = { some: [] };        // expect true
const test7 = { some: ['barry'] }; // expect false
const test8 = { some: new Map() }; // expect true
const test9 = {
  response: new Map([['body', new Map([['something', {}]])]]),
};                                 // expect true
const test10 = {
  response: '{"body":{"something":{}}}',
};                                 // expect true

const test11 = {
  something: { somethingElse: {} },
};                                 // expect true

assert.strictEqual(isEmpty(test1), true);
assert.strictEqual(isEmpty(test2), false);
assert.strictEqual(isEmpty(test3), true);
assert.strictEqual(isEmpty(test4), true);
assert.strictEqual(isEmpty(test5), true);
assert.strictEqual(isEmpty(test6), true);
assert.strictEqual(isEmpty(test7), false);
assert.strictEqual(isEmpty(test8), true);
assert.strictEqual(isEmpty(test9), true);
assert.strictEqual(isEmpty(test10), true);
assert.strictEqual(isEmpty(test11), true);

我创建的函数适用于大多数这些测试用例,但并非适用于所有测试用例。 我正在努力涵盖的是嵌套对象和 strignified 对象。我对如何继续感到有点困惑。

我如何检查后面的这些测试用例?

编辑:

const test12 = {
  something: {
    somethingElse: {
      number: 1,
      someSet: new Set(['garry']),
    },
  },
}; // should evaluate to false

const test13 = new Map([
    ['something', new Map([
        ['somethingElse', new Map([
            ['number', 1],
            ['someSet', new Set(['garry'])]
        ])]
    ])]
]); // should also evaluate to false

我认为解决这个问题的唯一方法是使用递归

您首先必须确定您当前使用的是哪些数据,然后查看数据中是否包含任何内容。如果他们有,你必须再次调用函数 isEmpty 来检查内部数据的类型,以及他们是否有内部数据。

const isEmpty = value  =>{
  if(typeof value === 'object'){
    if(Object.keys(value).length === 0) return true
    for (const property in value) {
     isEmpty(property)
    }
    
    
  }
  else if(typeof value === 'string'){
    //check for string 
  }
  //...
  //...
  //...
  //another types
}

你可以像这样使用递归函数:

  • 检查传递的值是否为对象
  • 如果对象有values函数,则使用Array.from(o.values())获取对象的值(获取SetMap和[=16的值=] 个对象)
  • 对每个值递归调用 isEmpty
  • 如果输入的值是一个字符串,则检查它是否为真值(您可以根据需要自定义这部分)
function isEmpty(o) {
  if (typeof o === "object") {
    let values = typeof o.values === "function"
                  ? Array.from(o.values())
                  : Object.values(o)
    
    return values.every(isEmpty)
  } else {
    var parsed = parseJsonString(o)
    return parsed ? isEmpty(parsed) : !o
  }
};

function parseJsonString(str) {
    try {
        return typeof str === 'string' && JSON.parse(str);
    } catch (e) {
        return '';
    }
}

这是一个可运行的片段:

function isEmpty(o) {
  if (typeof o === "object") {
    let values = typeof o.values === "function"
                  ? Array.from(o.values())
                  : Object.values(o)
    
    return values.every(isEmpty)
  } else {
    var parsed = parseJsonString(o)
    return parsed ? isEmpty(parsed) : !o
  }
};

function parseJsonString(str) {
    try {
        return typeof str === 'string' && JSON.parse(str);
    } catch (e) {
        return '';
    }
}

const test1 = {};                  // expect true
const test2 = { some: 'value' };   // expect false
const test3 = { some: {} };        // expect true
const test4 = [];                  // expect true
const test5 = [[]];                // expect true
const test6 = { some: [] };        // expect true
const test7 = { some: ['barry'] }; // expect false
const test8 = { some: new Map() }; // expect true
const test9 = {
  response: new Map([['body', new Map([['something', {}]])]]),
};                                 // expect true
const test10 = {
  response: '{"body":{"something":{}}}',
};                                 // expect true

const test11 = {
  something: { somethingElse: {} },
};                                // expect true

const test12 = {
  something: {
    somethingElse: {
      number: 1,
      someSet: new Set(['garry']),
    }
  }
};                                // expect false

const test13 = new Map([
    ['something', new Map([
        ['somethingElse', new Map([
            ['number', 1],
            ['someSet', new Set(['garry'])]
        ])]
    ])]
])                                // expect false

console.log(
  [test1, test2, test3, test4, test5, test6, test7, test8, test9, test10, test11, test12, test13].map(isEmpty)
);