Javascript - 递归查找数组中具有空值的键

Javascript - Recursively looking for keys in array with empty values

我创建了一个函数来递归查找嵌套数组中的空值。

函数 returns 一开始是正确的值,但似乎在返回结果之前将其重置为输入值。

我错过了什么?

这是我的代码:

const obj = [
  {
    mainContact: true,
    contactName: "",
    emailId: "abc@gmail.com",
    contactAddress: [
      {
        addressType: "",
        county: "U.K.",
        postCode: "MK7 6BZ",
        houseFlatNumber: 1
      },
      {
        addressType: "def",
        county: "France",
        postCode: "123MKO",
        houseFlatNumber: "223"
      }
    ],
    phoneDetails: [
      {
        notes: "",
        phoneNumber: "1234567899",
        countryCode: "44",
        priority: "1"
      },
      {
        notes: "Lorem ipsum",
        phoneNumber: "1112223331",
        countryCode: "48",
        priority: "2"
      }
    ]
  }
];

function validObject(obj, isOk) {
  for (var propName in obj) {
    if (typeof obj[propName] === "object") {
      this.validObject(obj[propName], isOk);
    } else if (
      obj[propName] === null ||
      obj[propName] === undefined ||
      obj[propName] === ""
    ) {
      isOk = false;
      break;
    }
  }
  return isOk;
}

console.log(validObject(obj), true);
// This should return false but it returns true although it first hit the return isOk line
// with a false value then set it back to true

如有任何帮助,我们将不胜感激。

谢谢。

基本问题是您没有返回递归调用的值。所以你实际上在做的是执行一个内联递归循环,然后从父调用返回值。

另外,因为isOk是一个原始布尔值,所以它是按值传递而不是按引用传递。因此在子函数调用中修改 isOk 不会修改父作用域中的变量。

注意:这不适用于 obj[propName](通过引用传递),因此对函数内部数据的任何修改都将保留在函数外部。

function validObject(obj) {
  for (var propName in obj) {
    if( typeof obj[propName] === "object" ) {
      if( validObject(obj[propName]) === false ) {
        // This will propergate back through the call stack
        return false;
     }
   } 
   else if (
     obj[propName] === null      || 
     obj[propName] === undefined || 
     obj[propName] === ''
   ) {
     return false;  // we don't need a variable here
   }
 }
 return true;  // calculatus eliminatus, nothing is false, so it must be true
}

关于递归的事情是您必须 return 来自递归调用的值。这意味着您从内部调用该函数,然后相应地处理 return 值。

这是我对你的函数的解释,我在其中添加了一个简单的基本情况来检查传递的值是 nullundefined 还是空字符串。

function isValidObject(obj) {
  // Base case
  if (obj[propName] === null || obj[propName] === undefined || obj[propName] === '') {
    return false;
  }

  // Recurse through each item in object
  if (typeof obj === "object") {
    for (var propName in obj) {
      if (!isValidObject(obj[propName]) {
        return false;
      }
    }
  }
  return true;
}

请注意,这允许您摆脱传递到函数中的布尔参数,而当找到第一个时 return false .

感谢 James McGuigan,我编辑的版本如下:

       isValidObject(obj) {

         for (var propName in obj) {
            if( typeof obj[propName] === "object" ) {
                if( this.isValidObject(obj[propName]) === false || 
                     obj[propName] === null || 
                     obj[propName].length === 0 ) 
                {
                     return false;
                }
            } 
            else if (
                      obj[propName] === null      || 
                      obj[propName] === undefined || 
                      obj[propName] === '' 
                    ) {
                         return false;  
                      }
            }
            return true;  

        }

另一种方法是编写一个更通用的函数来递归测试对象属性的有效性,给定要测试的谓词。

不难;在我看来,这通常比直接编写特定函数要简单。并将其应用到具体案例中也很简单。

它可能看起来像这样:

const isValid = (pred) => (obj) =>
  Object .values (obj) .every (
    v => (v && typeof v == 'object') ? isValid (pred) (v) : pred (v)
  )

const noEmptyProps = isValid (v => v !== '' && v != null)

const obj = [{mainContact: true, contactName: "", emailId: "abc@gmail.com", contactAddress: [{addressType: "", county: "U.K.", postCode: "MK7 6BZ", houseFlatNumber: 1}, {addressType: "def", county: "France", postCode: "123MKO", houseFlatNumber: "223"}], phoneDetails: [{notes: "", phoneNumber: "1234567899", countryCode: "44", priority: "1"}, {notes: "Lorem ipsum", phoneNumber: "1112223331", countryCode: "48", priority: "2"}]}]

console.log (noEmptyProps (obj))