【问题标题】:Adding element to existing object in an array results in the TypeError: Cannot set property 'live' of undefined将元素添加到数组中的现有对象会导致 TypeError: Cannot set property 'live' of undefined
【发布时间】:2020-06-23 11:55:14
【问题描述】:

我正在尝试将一个新的属性值推送到现有的 JSONArray 中,但是当我这样做时,我收到了错误 TypeError: Cannot set property 'live' of undefined

var ProxyData       =   [];

//Setting some of the fields outside the for loop
ProxyData.push({
                    'country'       :   country,
                    'ip'            :   ip,
                    'port'          :   port,
                    'createdAt'     :   createdAt,
                    'updatedAt'     :   updatedAt,
                    'provider'      :   'proxy11.com'
                });

//Based on some value I need to add thie live field
for(var item=0; item<ProxyData.length; item++)
{
    ProxyData[item].live    =   'Yes';

}

我想保留先前设置的对象,但同时基于 for 循环中的某些条件,我想将新字段 live 添加到数组中的对象中。我怎样才能做到这一点?

我也试过了,但没有运气: ProxyData[item]["live"] = "Yes";

我之前尝试定义 live 字段,以便稍后设置它,但仍然无法正常工作:

ProxyData.push({
                            'country'       :   country,
                            'ip'            :   ip,
                            'port'          :   port,
                            'createdAt'     :   createdAt,
                            'updatedAt'     :   updatedAt,
                            'provider'      :   'proxy11.com',
                            'live'          :   ''
                        });

我发布上面的代码是为了简单理解,但为了清楚起见,我将发布我项目中的完整代码:

var ProxyData       =   [];

for(var itemCount=0; itemCount<pageData.data.length; itemCount++)
{
    var country     =   pageData.data[itemCount].country;
    var ip          =   pageData.data[itemCount].ip;
    var port        =   pageData.data[itemCount].port;
    var createdAt   =   pageData.data[itemCount].createdAt;
    var updatedAt   =   pageData.data[itemCount].updatedAt;

    ProxyData.push({
        'country'       :   country,
        'ip'            :   ip,
        'port'          :   port,
        'createdAt'     :   createdAt,
        'updatedAt'     :   updatedAt,
        'provider'      :   'proxy11.com'
    });

    itemProcessed++;

    if(itemProcessed == pageData.data.length)
    {

        var     sql     =   " INSERT INTO TBL_PROXY (IP, COUNTRY, PORT, CREATED_DT_TM, UPDATE_DT_TM, PROVIDER) VALUES ";

        for(var item=0; item<ProxyData.length; item++)
        {
            var proxy       =   'http://'+ProxyData[item].ip+':'+ProxyData[item].port;
            var liveState   =   "";

            request({
                'url':'localhost:3000',
                'method': "GET",
                'proxy': proxy
            },function (error, response, body) {

                if (!error && response.statusCode == 200) {
                    ProxyData[item].live    =   'Yes';
                    console.log(ProxyData);
                }
                else
                {
                    ProxyData[item].live    =   'No';
                    console.log(ProxyData);
                }
            });

            sql         +=  util.format(" (%s', '%s', '%s', '%s', '%s', '%s') ", ProxyData[item].ip, ProxyData[item].country, ProxyData[item].port, ProxyData[item].createdAt, ProxyData[item].updatedAt, ProxyData[item].provider)+',';
        }



        sql     =   sql.slice(0, sql.length-1);

        db.Proxy_Feed_Data_Push(sql, function(data){
            callback(data);
        });
    }
}

【问题讨论】:

  • 你可以将你的json存储为对象let ProxyData = {...} 然后添加你想要的任何属性ProxyData.live = "yes"
  • 在 for 循环之前,我有另一个 for 循环,它最初填充 ProxyData。我在这里修改了代码,以便于回答。我以前试过这个,它已经奏效了,但由于某种原因,我现在可以让它工作了。
  • 代码按原样工作。在尝试使用之前将item 记录到控制台。
  • 当我尝试进一步继续时出现以下错误。如果我删除 ProxyData[item]["live"] = "Yes"; 一切正常。不确定是什么导致了问题。

标签: javascript node.js arrays json


【解决方案1】:

当您的异步调用完成时,“item”的值已经改变。尝试在function (error, response, body) { 之后添加console.log(item, ProxyData[item]); 以查看。

看这个现象的另一种方式是用这个简单的例子:

var ProxyData = ['a', 'b', 'c'];
for (var item = 0; item < ProxyData.length; item++) {
  Promise.resolve().then(() => {
    console.log(item, ProxyData[item]);
  });
}
// Results in:
// 3 undefined
// 3 undefined
// 3 undefined

modern JavaScript environments 中,只需使用let 而不是var 即可解决此问题。

由于var 的作用域是定义它的函数(而不是块),一种解决方法是(1)用函数包装每个循环迭代,(2)用值定义一个新变量(3)的 item 以便在同步调用完成时,它使用正确的特别为它定义的变量。

    for(var item=0; item<ProxyData.length; item++)
    {
        // (1) wrap in a IIFE
        // (2) define a new variable
        (function(item2) {

            var proxy       =   'http://'+ProxyData[item].ip+':'+ProxyData[item].port;
            var liveState   =   "";

            request({
                'url':'localhost:3000',
                'method': "GET",
                'proxy': proxy
            },function (error, response, body) {
                // Even though 'item' has changed by now,
                // the variable 'item2' is scoped to the function
                // inside the loop iteration so it's what you expect.

                if (!error && response.statusCode == 200) {
                    ProxyData[item2].live    =   'Yes';
                    console.log(ProxyData);
                }
                else
                {
                    ProxyData[item2].live    =   'No';
                    console.log(ProxyData);
                }
            });

            sql         +=  util.format(" (%s', '%s', '%s', '%s', '%s', '%s') ", ProxyData[item].ip, ProxyData[item].country, ProxyData[item].port, ProxyData[item].createdAt, ProxyData[item].updatedAt, ProxyData[item].provider)+',';

        // (3) pass the value of 'item', it'll be assigned to 'item2'
        })(item);
    }

可以item2 变量命名为item,但这可能会造成混淆。

或者只使用块范围的变量来代替定义函数:

    let item2 = item;
    // When you run your async call later, it'll have
    // the correct value because 'let' is scoped to the 
    // nearest block (which is 'for() {}').

【讨论】:

    猜你喜欢
    • 2018-12-16
    • 2014-12-22
    • 1970-01-01
    • 2020-03-22
    • 2018-01-26
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 2021-06-25
    相关资源
    最近更新 更多