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

Javascript-递归查找数组中具有空值的键,javascript,for-loop,recursion,nested-loops,Javascript,For Loop,Recursion,Nested Loops,我创建了一个递归查找嵌套数组中空值的函数 函数首先返回正确的值,但似乎在返回结果之前将其重置为输入值 我错过了什么 这是我的密码: const obj=[ { 主要联系人:对, 联系人姓名:“, 电子邮件ID:“abc@gmail.com", 联系地址:[ { 地址类型:“”, 郡:“英国”, 邮政编码:"MK7 6BZ",, 户数:1 }, { 地址类型:“def”, 县:“法国”, 邮政编码:"123MKO",, 公寓号码:“223” } ], 电话详情:[ { 注:“, 电话号码:“123

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

函数首先返回正确的值,但似乎在返回结果之前将其重置为输入值

我错过了什么

这是我的密码:

const obj=[
{
主要联系人:对,
联系人姓名:“,
电子邮件ID:“abc@gmail.com",
联系地址:[
{
地址类型:“”,
郡:“英国”,
邮政编码:"MK7 6BZ",,
户数:1
},
{
地址类型:“def”,
县:“法国”,
邮政编码:"123MKO",,
公寓号码:“223”
}
],
电话详情:[
{
注:“,
电话号码:“1234567899”,
国家代码:“44”,
优先次序:“1”
},
{
注:“Lorem ipsum”,
电话号码:“1112223331”,
国家代码:“48”,
优先次序:“2”
}
]
}
];
功能validObject(obj、isOk){
for(obj中的变量propName){
if(对象的类型[propName]=“对象”){
this.validObject(obj[propName],isOk);
}否则如果(
obj[propName]==null||
obj[propName]==未定义||
对象[propName]==“”
) {
isOk=假;
打破
}
}
返回isOk;
}
console.log(validObject(obj),true);
//这应该返回false,但它返回true,尽管它第一次到达返回isOk行
//使用false值,然后将其设置回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
}

递归的问题是,必须从递归调用返回值。这意味着您从函数本身内部调用函数,然后相应地处理返回值

下面是我对函数的解释,我添加了一个简单的基本情况来检查传递的值是
null
未定义的
,还是空字符串

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


请注意,这允许您删除传递到函数中的布尔参数,而在找到第一个参数时只返回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)=>
对象值(obj)。每个(
v=>(v&&typeof v=='object')?是否有效(pred)(v):pred(v)
)
const noEmptyProps=isValid(v=>v!=''&&v!=null)
const obj=[{mainContact:true,contactName:,emailId:“abc@gmail.com“,联系地址:[{地址类型:”,县:“英国”,邮政编码:“MK7 6BZ”,住房号码:1},{地址类型:“def”,县:“法国”,邮政编码:“123MKO”,住房号码:“223”},电话详细信息:[备注:”,电话号码:“1234567899”,国家代码:“44”,优先级:“1”},{注:“Lorem ipsum”,电话号码:“1112223331”,国家代码:“48”,优先级:“2”}]

console.log(noEmptyProps(obj))
什么是
haspendykey
?我认为
这个。haspendykey
应该是
validObject
。否则,它不是递归调用,只是一个带有单个for循环的函数。这并不能回答代码问题,但我做了一个函数,如果这里有空值,则返回false。抱歉,是的。haspendykey是错误的在这里复制代码时,我刚刚更改了命名,忘记了更新对递归函数的调用。应该是这样。validObject。我更喜欢你的解释:)非常感谢。我对函数做了一些小修改,但你的帮助非常重要。Main edgecase正在调用isValidObject()对于不是对象的事物,
isValidObject(null)==true
isValidObject(“字符串”)==true
isValidObject({})==true
isValidObject([])==true
解决这一问题的一种方法是使用一个父函数来检测顶级调用是否是对象(注意:数组也是对象,因此您还需要一行额外的代码来检测它们)。然后是一个子函数,用于检测有效属性,并从中递归迭代