首页 > 解决方案 > 嵌套数组元音搜索

问题描述

我编写了 2 个函数来搜索和计算嵌套数组中的字符串中的元音。第一个函数searchVowels进行实际搜索并计算元音。第二个函数countVowels只是声明vowels(counter) 变量,执行第一个函数并返回结果。我不得不这样做,因为第一个函数的递归性会产生多个声明并返回元音变量。

问题是:即使我vowelsvar关键字声明(范围应该是整个函数),内部searchVowels函数也看不到它。如果我将声明从函数中取出并设为vowels全局,则一切正常。所以我的问题是:为什么searchVowels看不到在父函数中vowels声明的变量?var

var nestedArr = [
    "Elie",
    ["Matt", ["Tim"]],
    ["Colt", ["Whisky", ["Janey"], "Tom"]],
    "Lorien"
];


function searchVowels(arr) {
    //iterating through each element of the array (or nested arrays in the subsequent calls)
    for (let i of arr) {
        //checking if the element i of the array is a string or another array
        if (typeof i === 'string') {
            //looping through the elements of the string
            for(let j of i) {
                //checking if the current element of the string is a vocal or not
                if (j === 'a' || j === 'e' || j === 'i' || j === 'o' || j === 'u' || j === 'A' || j === 'E' || j === 'I' || j === 'O' || j === 'U') {
                    vowels++;
                } 
            }
        //if the element i of the parent array is another array, the function calls itself and repeats everything on the  nested array (recursive)
        } else searchVowels(i);
    }
}


function countVowels (arr) {
    var vowels = 0;
    searchVowels (arr);
    return vowels;
}

countVowels(nestedArr);

标签: javascriptrecursionscope

解决方案


为什么 searchVowels 在父函数中看不到用 var 声明的元音变量?

因为 Javascript 是一种静态(词法)范围的语言,函数的父子关系取决于它们的编写方式,而不是它们的调用方式(这将是“动态”范围)。

为了使事情按预期工作,您必须将子函数以文本形式放置在父函数中:

function countVowels (arr) {
    var vowels;

    function searchVowels(arr) {
        ...
    }
}

一般来说,尽量避免使用修改外部变量或以其他方式改变外部世界(“副作用”)的函数。以“纯”方式设计函数要好得多,这样它们就只接受参数和返回值——就像数学函数一样。例子:

function countVowels(arr) {
    let count = 0;

    for (let item of arr) {

        if (Array.isArray(item))
            count += countVowels(item)
        else
            for (let char of item.toUpperCase()) {
                if ('AEIOU'.includes(char)) {
                    count++
                }
            }
    }

    return count
}

在这里,每个递归副本countVowels分配自己的本地计数器并将其返回给调用者,然后调用者负责将其添加到自己的计数器等等,直到达到最高级别。


推荐阅读