在 for 循环中,为什么 i++ 在第二次使用后变为 1

In for loop, why does i++ change to 1 after second use?

本文关键字:i++ 循环 for 为什么 第二次      更新时间:2023-09-26

为什么我的 var i in for 循环从 0 变为 1?

这一行:for for (var i = 0; i

结果是通过方法调用(推送)到未定义的元素而出错。

var newsUpdates = {};
var siteDatabase = [
    "http://example.to"
];
var scraperjs = require('scraperjs');
for (var i = 0; i < siteDatabase.length; i++) {
    news[siteDatabase[i]] = [];
    scraperjs.StaticScraper.create(siteDatabase[i])
        .scrape(function($) {
            return $(".lang_English").map(function() {
                return $(this).children('td').eq(1).children(
                    'a').last().text();
            }).get();
        }, function(news) {
            for (var x = 0; x < news.length; x++) {
                if (news[x] == '') {
                    news.splice(x, 1);
                }
            }
            for (var x = 0; x < news.length; x++) {
                // i in siteDatabase[i] is not 0, but 1??
                newsUpdates[siteDatabase[i]].push({
                    "title": news[x]
                });
                // TypeError: Cannot call method 'push' of undefined
            }
            console.log(newsUpdates);
        })
}

问题出在我在代码之间评论的区域。

您传递给.scrape的函数具有对i变量的持久引用,而不是创建函数时的副本。因此,它使用函数运行时i值,这(大概)是在循环结束后,当i的值发生变化时。

在这种情况下,我可能会使用构建器函数来构建回调,以便回调关闭不会更改的内容:

var newsUpdates = {};
var siteDatabase = [
    "http://example.to"
];
var scraperjs = require('scraperjs');
for (var i = 0; i < siteDatabase.length; i++) {
    news[siteDatabase[i]] = [];
    scraperjs.StaticScraper.create(siteDatabase[i])
        .scrape(function($) {
            return $(".lang_English").map(function() {
                return $(this).children('td').eq(1).children(
                    'a').last().text();
            }).get();
        }, buildCallback(i))
}
function buildCallback(index) {
    return function(news) {
        for (var x = 0; x < news.length; x++) {
            if (news[x] == '') {
                news.splice(x, 1);
            }
        }
        for (var x = 0; x < news.length; x++) {
            newsUpdates[siteDatabase[inindex]].push({
                "title": news[x]
            });
        }
        console.log(newsUpdates);
    };
}

在那里,我们从buildCallback返回的函数在index参数上关闭,其值永远不会改变。然后我们i传递到它,以便构建我们的回调。

由于siteDatabase似乎是一个数组,解决此问题的另一种方法是使用 siteDatabase.forEach ,这将为每次迭代提供一个单独的闭包变量。我更喜欢这种方法而不是构建器函数方法,因为它更直接且易于遵循:

var newsUpdates = {};
var siteDatabase = [
    "http://example.to"
];
var scraperjs = require('scraperjs');
siteDatabase.forEach(function (site) {
    scraperjs.StaticScraper.create(site)
    .scrape(function($) {
        return $(".lang_English").map(function() {
            return $(this).children('td').eq(1)
                          .children('a').last().text();
        }).get();
    }, function(news) {
        newsUpdates[site] = news.filter(function (item) {
            return item != '';
        }).map(function (item) {
            return { title: item };
        });
        console.log(newsUpdates);
    });
});

您可以进一步将其分解为函数,以使其更清晰,更具表现力:

var newsUpdates = {};
var siteDatabase = [
    "http://example.to"
];
var scraperjs = require('scraperjs');
function scrapePageNewsItems($) {
    return $(".lang_English").map(function() {
        return $(this).children('td').eq(1)
                      .children('a').last().text();
    }).get();
}
function notBlank(item) {
    return item != '';
}
function convertNewsItem(item) {
    return { title: item };
}
function convertNewsItems(news) {
    return news.filter(notBlank).map(convertNewsItem);
}
siteDatabase.forEach(function (site) {
    scraperjs.StaticScraper.create(site)
    .scrape(scrapePageNewsItems, function(news) {
        newsUpdates[site] = convertNewsItems(news);
        console.log(newsUpdates);
    });
});