【问题标题】:Javascript 'undefined' when using a function variable on an array of objects在对象数组上使用函数变量时的Javascript“未定义”
【发布时间】:2012-01-08 14:49:50
【问题描述】:

我有以下(示例)对象数组:

var theArray = [
    {theId:'1', num: 34},
    {theId:'2', num: 23},
    {theId:'5', num: 26}
];

还有这个函数,它可以很好地循环它们:

function printValues() {
    var i = 0;
    for(i; i<theArray.length; i++) {
        var obj = theArray[i];
        document.getElementById('result1').innerHTML += obj.theId + ' = ' + obj.num + '<br>';
    }
}

但是,如果我想通过使用函数变量访问其中的对象来抽象此函数以用于类似数组,如下所示:

function printValuesVar(arr,elemId,arrId,arrNum) {
    var i = 0;
    for(i; i<arr.length; i++) {
        var obj = arr[i];
        document.getElementById(elemId).innerHTML += obj.arrId + ' = ' + obj.arrNum + '<br>';
    }
}

'undefined' 是如下调用的结果(正如我所期望的那样,因为 'arrId' 不是对象名称):

printValuesVar(theArray,'result2','theId','num');

如何使用传递给函数变量的值按名称访问数组中对象的值?


针对反模式重写了以下建议:

function printValuesVar(arr,elemId,arrId,arrNum) {
    var i = 0;
    var content = '';
    for(i; i<arr.length; i+=1) {
        var obj = arr[i];
        content += obj[arrId] + ' = ' + obj[arrNum] + '<br>';
    }
    document.getElementById(elemId).innerHTML = content;
}

【问题讨论】:

  • 您的代码包含几个反模式:(1)您在循环中通过getElementById 查询 - 没有必要这样做。只需事先获得参考; (2) 您在循环内分配给innerHTML - 再次不需要。您希望将 DOM 操作保持在最低限度。用循环构造 HTML 字符串,然后在循环之后 赋值给innerHTML
  • +1 获得指导 - 因为这是一个学习过程,所以我重写了函数(在上面添加)以纳入您的建议,之前查看下面的示例。现在我将尝试 PointedEars 的建议。

标签: javascript arrays function object undefined


【解决方案1】:

试试这个:

function printValuesVar( arr, elemId, arrId, arrNum ) {
    var content = '';

    arr.forEach( function ( arrElem ) {
        content += arrElem[ arrId ] + ' = ' + arrElem[ arrNum ] + '<br>';
    });

    document.getElementById( elemId ).innerHTML = content;
}

或者更高级一点:

function printValuesVar( arr, elemId, arrId, arrNum ) {
    document.getElementById( elemId ).innerHTML = arr.map( function ( arrElem ) {
        return arrElem[ arrId ] + ' = ' + arrElem[ arrNum ];
    }).join( '<br>' );
}

ES5-shim for shitty browsers

【讨论】:

  • 而不是循环中的连续字符串连接 (+=),请考虑将 push 转换为 Array,稍后再使用 join。一个简单的for 循环可能比forEachmap 中的任何一个都更有效且明显更兼容。
  • @PointedEars 我的第二个示例使用join() 而不是+= 字符串连接。数组迭代方法没有在 IE8 中实现,但您可以轻松地填充该浏览器。至于效率,确实for比数组方法稍微快一点,但是that doesn't mean it's preferred
  • var content = []; for (var i = 0, len = arr.length; i &lt; len; ++i) { var arrElem = arr[i]; content.push(arrElem[arrId] + ' = ' + arrElem[arrNum]); } ….innerHTML = content.join("&lt;br&gt;"); 可能比来自forEach 的连续函数调用更快并且明显更兼容。至于 Crockford 的参考文献,这种谬误被称为“权威论证”,或ipse dixit
  • @PointedEars 不,这不是权威的论点。如果我说:“这更好,因为 Crockford 是这么说的。” 来自权威的论点。我不这样做。我的链接指向视频中 Crockford 解释为什么数组迭代方法优于 for 循环的部分。引用:“速度差异并不显着,而用代码表达事物的方式的好处是非常深远的。”。这就是我要提出的论点。
  • @DaveEveritt 没有arr.prototype.forEach。 Crockford (et al.) 在未定义 Array.prototype.forEach 时对其进行定义,以便 arr 引用的 Array 实例可以通过原型链继承该方法。您可以这样做,但是如果您想将 for..in 迭代与 Array 实例一起使用(这对于稀疏数组很方便),则需要采取预防措施,因为新的用户定义属性也是可枚举的。 (替代方案是Object.defineProperty(),但如果你有,你已经有Array.prototype.forEach等)
【解决方案2】:

因为您正在寻找密钥“arrId”,而不是存储在变量 arrId 中的密钥

document.getElementById(elemId).innerHTML += obj[arrId] + ' = ' + obj[arrNum] + '<br>';

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 2012-10-09
    • 1970-01-01
    • 1970-01-01
    • 2018-09-17
    • 1970-01-01
    相关资源
    最近更新 更多