迭代器范围不是本地的

Iterator scope not local?

本文关键字:范围 迭代器      更新时间:2023-09-26

我只是在编写两个JavaScript函数,其中一个接受一个长字符串,循环到它到达一个空格,然后调用另一个函数将空格之前的输入打印到DOM中。 然后,第一个函数将继续在空格之后输入,点击空格,调用打印函数等。

在这个过程中,我一直在打无限循环,但前提是字符串包含一个空格。 我不知道为什么,因为所有的循环似乎都设置正确。 我最终发现我的迭代器变量正在将范围从我的第二个函数printMe跳回第一个函数,readAndFeed,并且由于函数的设置方式,如果涉及空格,它将始终以低于终止值的数字返回。

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

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作为迭代器。

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

我很困惑;这似乎不像我理解变量范围的方式。 这些函数是单独定义的,因此似乎迭代器应该是这些函数的本地函数,并且不能从一个函数跳到另一个函数。

这是一个jsfiddle

取消注释底部的"是示例"部分以使浏览器崩溃。 同样,在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++)