Javascript 显式贴花“let”对带有递归的for循环变量有什么影响?

Javascript 显式贴花“let”对带有递归的for循环变量有什么影响?,javascript,node.js,for-loop,recursion,Javascript,Node.js,For Loop,Recursion,我有一个函数的示例代码,它通过递归遍历一个数组及其所有子数组,并计算找到的匹配字符串的数量 示例阵列: 我的函数可以遍历这个数组,并计算数组中的对象数 此代码运行良好: 然而 这是我不明白的部分,需要解释一下。如果我删除forloop变量i上的let声明,并隐式声明它i=0 当您使用隐式声明的变量时,您将只有一个这样的变量,与您在递归树中的位置无关。它将是一个全局变量 这将有效地破坏算法的逻辑,因为最深的递归级别将把i的值移到数组长度之外,然后当在上一个递归级别回溯循环时,会突然跳到i的值,可能

我有一个函数的示例代码,它通过递归遍历一个数组及其所有子数组,并计算找到的匹配字符串的数量

示例阵列:

我的函数可以遍历这个数组,并计算数组中的对象数

此代码运行良好:

然而
这是我不明白的部分,需要解释一下。如果我删除forloop变量i上的let声明,并隐式声明它i=0 当您使用隐式声明的变量时,您将只有一个这样的变量,与您在递归树中的位置无关。它将是一个全局变量

这将有效地破坏算法的逻辑,因为最深的递归级别将把i的值移到数组长度之外,然后当在上一个递归级别回溯循环时,会突然跳到i的值,可能会跳过它应该处理的几个有效数组项


始终声明变量。

当您使用隐式声明的变量时,您将只有一个这样的变量,与您在递归树中的位置无关。它将是一个全局变量

这将有效地破坏算法的逻辑,因为最深的递归级别将把i的值移到数组长度之外,然后当在上一个递归级别回溯循环时,会突然跳到i的值,可能会跳过它应该处理的几个有效数组项

始终声明变量

…并隐式声明它i=0

这不是一个声明,它只是创建一个*。因为它是全局的,所以所有对SearchArray的调用都会共享它,所以您的外部调用会提前结束,因为您的内部调用增加了i

例如:

带有DeclarationRecurse的函数{ 对于设i=0;i<3;++i{ console.logrecurse?外部:内部+i; 如果递归{ withDeclarationfalse; } } } 不带DeclarationRecurse的函数{ 对于i=0;i<3;++i{ console.logrecurse?外部:内部+i; 如果递归{ 无声明错误; } } } console.logWith声明:; withDeclarationtrue; console.logWithout声明:; withoutDeclarationtrue; .作为控制台包装{ 最大高度:100%!重要; } …并隐式声明它i=0

这不是一个声明,它只是创建一个*。因为它是全局的,所以所有对SearchArray的调用都会共享它,所以您的外部调用会提前结束,因为您的内部调用增加了i

例如:

带有DeclarationRecurse的函数{ 对于设i=0;i<3;++i{ console.logrecurse?外部:内部+i; 如果递归{ withDeclarationfalse; } } } 不带DeclarationRecurse的函数{ 对于i=0;i<3;++i{ console.logrecurse?外部:内部+i; 如果递归{ 无声明错误; } } } console.logWith声明:; withDeclarationtrue; console.logWithout声明:; withoutDeclarationtrue; .作为控制台包装{ 最大高度:100%!重要;
} TJ和Trincot在修复您的程序方面做得很好–我将尝试修复您的想法

递归是一种功能遗产

递归是一个源于函数风格的概念。将它与命令式风格混合在一起会给新程序员带来很多痛苦和困惑

,我们确定了基本情况和归纳情况

基本情况–输入的第一个值为空-如果输入为空,则显然没有匹配项,因此返回0 归纳案例1–first不是空的,但它是一个数组–在first上递归加上在其余值上递归 归纳案例2-first不是空的,也不是数组,因此它是一个普通值-如果first匹配,则为匹配返回1加上对其余值重复出现的结果 归纳情况3-第一个不是空的,不是数组,也不匹配-在其余值上重复出现 由于这一实施,所有的痛苦和痛苦都从程序中消除了。我们不关心局部状态变量、变量重新分配、数组迭代器、递增迭代器或其他类似的副作用

为了简洁起见,我将数据中的“某物”和“任何东西”分别替换为“A”和“B”

常数为空= 象征 const searcharray=match,[first=Empty,…rest]=> { /*没有价值*/ 如果第一个===空 返回0 /*值不为空*/ 否则,请先使用Array.isArray 返回searchArrays匹配,first+searchArrays匹配,rest /*值不是数组*/ 如果第一个===匹配,则为else 返回1+个匹配的搜索数组,其余 /*值不匹配*/ 其他的 返回搜索数组匹配,其余 } 常量数据= [A'、[A'、[A'、[A']、[A'、[A'、[A'、[A']、[A'、[A']、[A'、[B']、[A'、[A'、[A'、[A'、[A'、[A']、[A'、[A'、[A'、], “A”、“B”、“A”、“A”、“B”、“B”] console.log searchArray“A”,数据//18 console.log SearchArray“B”,数据//4
console.log searchArray'C',data//0TJ和Trincot在修复您的程序方面做得很好–我将尝试修复您的想法

递归是一种功能遗产

递归是一个源于函数风格的概念。将它与命令式风格混合在一起会给新程序员带来很多痛苦和困惑

,我们确定了基本情况和归纳情况

基本情况–输入的第一个值为空-如果输入为空,则显然没有匹配项,因此返回0 归纳案例1–first不是空的,但它是一个数组–在first上递归加上在其余值上递归 归纳案例2-first不是空的,也不是数组,因此它是一个普通值-如果first匹配,则为匹配返回1加上对其余值重复出现的结果 归纳情况3-第一个不是空的,不是数组,也不匹配-在其余值上重复出现 由于这一实施,所有的痛苦和痛苦都从程序中消除了。我们不关心局部状态变量、变量重新分配、数组迭代器、递增迭代器或其他类似的副作用

为了简洁起见,我将数据中的“某物”和“任何东西”分别替换为“A”和“B”

常数为空= 象征 const searcharray=match,[first=Empty,…rest]=> { /*没有价值*/ 如果第一个===空 返回0 /*值不为空*/ 否则,请先使用Array.isArray 返回searchArrays匹配,first+searchArrays匹配,rest /*值不是数组*/ 如果第一个===匹配,则为else 返回1+个匹配的搜索数组,其余 /*值不匹配*/ 其他的 返回搜索数组匹配,其余 } 常量数据= [A'、[A'、[A'、[A']、[A'、[A'、[A'、[A']、[A'、[A'、[B']、[A'、[A'、[A'、[A'、[A'、[B'、[A'、[A'、[A'、[B']、[B'] console.log searchArray“A”,数据//18 console.log SearchArray“B”,数据//4
console.log searchArray“C”,data//0内部函数始终可以访问父函数中声明的变量,该父函数称为闭包!。所以你每次重置i的值,因此是无限的looping@deven98602:虽然这是真的,但它与OP的代码无关,OP的代码没有嵌套函数。内部函数始终可以访问父函数中声明的变量(称为闭包!)!。所以你每次重置i的值,因此是无限的looping@deven98602:虽然这是真的,但它与OP的代码无关,OP的代码没有嵌套函数。哇,这个答案太棒了。我不得不做很多术语补习,我不知道符号是什么,…其余的是什么,然后再通读一遍你们的解释和例子。非常感谢,这是一次很好的学习经历!有一件事我在语法方面不理解:在const searcharray=match中,[first=Empty,…rest]first=Empty是必要的还是为了清楚起见?`const searchArrays=match,[first,…rest]是否可以同样工作?再次感谢这太棒了!此外,我还将进一步研究您关于强大抽象的帖子,因为我认为这比我目前的水平还高。@CodeAt30很乐意提供帮助。如果您更改为[first,…rest],您只需将first===Empty更改为first==undefined-这是我对显式与隐式停止值的评论^哇,这个答案太棒了。我不得不做很多术语补习,我不知道符号是什么,…其余的是什么,然后再通读一遍你们的解释和例子。非常感谢,这是一次很好的学习经历!有一件事我在语法方面不理解:在const searcharray=match中,[first=Empty,…rest]first=Empty是必要的还是为了清楚起见?`const searchArrays=match,[first,…rest]是否可以同样工作?再次感谢这太棒了!此外,我还将进一步研究您关于强大抽象的帖子,因为我认为这比我目前的水平还高。@CodeAt30很乐意提供帮助。如果您更改为[first,…rest],您只需将first===Empty更改为first===undefined——这是我对显式与隐式停止值的评论^_^
const array = [
    'something',
    'something',
    [
        'something',
        'something'
    ],
    'something',
    [
        'something',
        [
            'something',
            'something'
        ],
        'something',
        [
            [
                'something',
                'something',
                [
                    'anything'
                ]
            ],
            'something',
        ],
        [
            'something',
            [
                'something',
                'something',
                'something',
                [
                    'anything',
                    'something',
                    [
                        'something',
                        'anything'
                    ]
                ]
            ]
        ]
    ],
    'anything'
];
let somethingsFound = 0;
const searchArrays = (array, stringMatch) => {
    for(let i=0;i<array.length;i++){
        const item = array[i];
        if((typeof item) === 'string'){
            (item === stringMatch) ? somethingsFound++ : undefined;
        } else if ((typeof item) === 'object'){
            searchArrays(item, stringMatch);
        }
    }
}

searchArrays(array, 'something');
console.log(`Found ${somethingsFound} somethings`);
>Found 18 somethings
let somethingsFound = 0;
const searchArrays = (array, stringMatch) => {
    for(i=0;i<array.length;i++){
        const item = array[i];
        if((typeof item) === 'string'){
            (item === stringMatch) ? somethingsFound++ : undefined;
        } else if ((typeof item) === 'object'){
            searchArrays(item, stringMatch);
        }
    }
}

searchArrays(array, 'something');
console.log(`Found ${somethingsFound} somethings`);