迭代器作用域不是局部的?

Iterator scope not local?

我刚写了两个 JavaScript 函数,其中一个接受一个长字符串,循环遍历它直到遇到 space,然后调用另一个函数在space 变成了 DOM。然后第一个函数将在 space 之后继续输入,点击 space,调用打印函数等

在这个过程中,我不断遇到无限循环,但前提是字符串包含 space。我不明白为什么,因为所有循环似乎都设置正确。我最终发现我的迭代器变量正在跳出我的第二个函数 printMe 的范围并返回到第一个 readAndFeed,并且由于函数的设置方式,它总是会返回为如果涉及 space,则数字小于终止值。

第一个函数的循环如下所示:

function readAndFeed(content){

var output = "";
var len = content.length;

for(i = 0; i < len; i++)
    {

        console.log(i+" r and f increment")
        if(content[i] == (" "))
        {
            printMe(output);
            output = "";
        }
        else if(i==len-1){
            output += content[i];
            printMe(output)
        }
        else 
        {
          output += content[i]
        }
    }
}

第二个函数是 printMe(),它遍历字符串,将其分成三位,分别遍历每一位(不是以嵌套方式),并将它们打印到 DOM.我在里面用了类似的循环,我也用了i作为迭代器。

这将循环遍历没有 space 的字符串就好了,但是如果我在其中输入 space,浏览器就会崩溃。我尝试了很多不同的东西,但最终(通过记录迭代器值)意识到 i 出了问题。有效的方法是将 printMe 函数中的 i 更改为 j.

我很困惑;这似乎不像我对变量作用域的理解。这些函数是单独定义的,因此迭代器似乎应该是这些函数的局部函数,并且不能跳出一个函数进入另一个函数。

Here's a jsfiddle

取消注释底部的 "is an example" 部分会使浏览器崩溃。同样,将 printMe 函数中的 i 变量更改为 j 完全解决了这个问题,但是哇?

当你不声明变量时,它是隐式全局的。由于您尚未声明循环迭代索引 i,因此它是全局的。如果您在多个函数中这样做,这些全局变量将发生冲突,并且一个函数将意外修改另一个函数的变量。

解决方案是确保使用 var 声明局部变量,如:

for (var i = 0; i < len; i++) {

在您的情况下,您需要修复 readAndFeed()printMe(),因为它们都有相同的问题,因此它们都尝试使用全局 i。当你从另一个调用一个时,它会破坏原来对 i 的使用。这是 readAndFeed() 的固定版本:

function readAndFeed(content) {

    var output = "";
    var len = content.length;

    // add var here before i
    for (var i = 0; i < len; i++) {

        console.log(i + " r and f increment")
        if (content[i] == (" ")) {
            printMe(output);
            output = "";
        } else if (i == len - 1) {
            output += content[i];
            printMe(output)
        } else {
            output += content[i]
        }
    }
}

如果您 运行 您的 Javascript 代码处于严格模式,那么尝试使用未声明的变量实际上会导致错误(而不是隐式地使其成为全局变量),因此您不会意外射击自己这样的脚。

在您的示例中,i 实际上是一个全局变量。任何不带 var 语句的未声明变量赋值都声明了一个隐式全局变量。

要使 i 本地化,只需包含 var:

for (var i = 0; i < len; i++)