Javascript 在for循环中,为什么i++;第二次使用后改为1?

Javascript 在for循环中,为什么i++;第二次使用后改为1?,javascript,jquery,web-scraping,Javascript,Jquery,Web Scraping,为什么for循环中的var i从0变为1? 此行:for(var i=0;i

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

此行:for(var i=0;i 结果是对未定义元素的方法调用(push)出错

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);
        })
}
var newsUpdates={};
站点数据库=[
"http://example.to"
];
var scraperjs=需要(“scraperjs”);
对于(var i=0;i

问题出在代码之间的注释区域。

您要传递到的函数
。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);
    };
}
var newsUpdates={};
站点数据库=[
"http://example.to"
];
var scraperjs=需要(“scraperjs”);
对于(var i=0;i

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

传递到
中的函数。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);
    };
}
var newsUpdates={};
站点数据库=[
"http://example.to"
];
var scraperjs=需要(“scraperjs”);
对于(var i=0;i

在那里,我们从
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);
    });
});

由于
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);
    });
});

可能复制的可能复制的辉煌!这是可行的,但是如果我把I改成j,为什么会得到相同的结果呢?如果.scrape使用var i,那么var j不会受到影响,但它是…?我的意思是,如果我将for循环中的var i计数器更改为var j,为什么var j计数器仍然受到影响,即使它不是i。@combatmath:如果你真的用
j
替换了所有
i
,它也会受到影响。太棒了!这是有效的,但是如果我改变它,为什么会得到同样的结果呢