Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/426.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用递归函数正确确定多维javascript对象中是否存在键_Javascript_Recursion - Fatal编程技术网

如何使用递归函数正确确定多维javascript对象中是否存在键

如何使用递归函数正确确定多维javascript对象中是否存在键,javascript,recursion,Javascript,Recursion,我试图创建一个递归函数,该函数将在多维对象中循环,并测试键是否存在于单独的对象中。如果键不存在,我想中断循环并返回false;如果所有键都存在,我想返回true 我遇到的问题是,函数似乎总是返回true。以下是我正在使用的代码: var properties = {'global': {'structure' : {'body': {}}}}; var testExists = {'global': {'structure': {'test': 'value'}}}; if( ! this.

我试图创建一个递归函数,该函数将在多维对象中循环,并测试键是否存在于单独的对象中。如果键不存在,我想中断循环并返回false;如果所有键都存在,我想返回true

我遇到的问题是,函数似乎总是返回true。以下是我正在使用的代码:

var properties = {'global': {'structure' : {'body': {}}}};

var testExists = {'global': {'structure': {'test': 'value'}}};

if( ! this.exists(properties, testExists)) {
   console.log("DOESNT EXIST");
}


exists: function(destination, source) {
    var exists = true;

    check:
    for (var property in source) {

        if(destination[property]) {
            arguments.callee(destination[property], source[property]);
        }
        else
        {
            exists = false;
            break check;
        }
    }

    console.log(exists);

    return exists;
},

当我查看控制台以查看“exists”的值时,我看到两行,第一行为false,第二行为true,因此我创建的递归肯定存在错误

您的问题似乎是没有使用递归调用函数的结果

此外,您不应该使用
参数.callee
,而应该使用函数名,并在枚举其属性之前检查参数是否为对象。您可能还想检查
目的地
的属性是否不在枚举

试试这个:

function equal(destination, source) {
    if (Object(destination)!==destination || Object(source)!==source)
        // at least one of them is a primitive value
        return destination == source; // maybe use strict equality === ?
    for (var prop in source)
        if (!(prop in destination) || !equal(source[prop], destination[prop]))
            return false;
    return true;
}

你让事情变得比需要的更复杂:

function exists(destination, source) {
    for (var property in source) {
        if(destination.hasOwnProperty(property)) {
            if (!exists(destination[property], source[property])) {
                return false;
            }
        } else {
            return false;
        }
    }

    return true;
}​
注意.hasOwnProperty意味着这将只比较对象的直接属性,而不是从原型继承的属性。我以为这就是你要找的

还要注意:它实际上使用递归调用的结果,它正确地递归,它使用.hasOwnProperty而不是仅仅检查错误,并且它不使用中间变量来存储结果(无论如何,在递归中使用它们的方式是行不通的)


还有一件事:这只会“单向”,即目标中不在源中的任何属性都不会被检查。要检查这两种方法,您必须调用它两次或将其扩展为循环两次。

在执行代码时,我看到
false
true
true
-您期望什么?我想在出现false时立即中断循环/函数并返回false。因此,当到达testExists对象中的键“test”时,因为它不存在于properties对象中,我希望函数返回false对于该对象,您的函数确实返回了
false
,但是该返回值并不会阻止调用函数返回
true
。请注意,您可以命名函数并将其分配给对象属性或变量。如果同时执行这两种操作,函数名将仅在函数内部可见,这意味着您仍然可以递归调用它,而不会污染名称空间。这是两全其美的。如果其中任何一个参数都是“真实对象”,那么就不需要进行那种笨拙的检查,因为..in将愉快地对数字或字符串进行操作。另一方面,hasOwnProperty很重要。@Kiyura:
for in
将愉快地在
Number
/
String
.prototype
上循环任何可枚举属性。它也将在普通对象上循环任何可枚举属性。正如我在回答中所指出的,重要的是要包含一个hasOwnProperty检查,或者干脆用它完全取代falsy检查。这不一定是想要的,也不符合实际情况。只要检查一下当使用
exists({proof:“someString”},{proof:{toString:{oops:true}}}})调用函数时,函数会做什么。
函数不会检查对象的所有属性,您应该提及或修复它。这不是我的论点-您的函数无法处理具有多个属性的对象。此函数要么总是返回false,要么我收到“超过最大调用堆栈大小”错误听起来像是在对大型对象调用此函数。递归函数总是有超过调用堆栈大小的风险。如果希望它在任意大小的对象上工作,则需要迭代地重新实现。您能用一个较小的示例(在JSFIDLE中)演示它在不希望返回false时是如何返回false的吗?你明白这个函数在做什么吗?这会为我生成一个“超过最大调用堆栈大小”错误-