覆盖对象的长度属性

时间:2012-07-10 23:40:08

标签: javascript

我发现自己处于一个有趣的境地。我使用对象文字来表示现实世界中的产品。现在每个产品都有与其相关的长度以用于运输目的。它看起来像这样:

var product = {
  name: 'MacBook Pro 15 Inch',
  description: 'The new macbook pros....',
  length: 15
  height: 15
  Weight: 4
}

这很好用。但对于长度未知的产品,它们默认长度为-1。

再一次这样可行,直到你尝试这样做:

console.log('Product has the following properties');
_.each(product, function(val, key) {
    console.log(key + ":" + val);
});

对于长度为-1的商品,不会打印任何键。为什么?好吧,因为内部下划线使用length属性,Javascript中的每个对象都必须遍历传入对象的所有属性。由于我们覆盖了该值,现在它是-1,因为我们开始在i = 0循环,所以循环永远不会被执行。

现在提出问题,如何防止覆盖长度属性?防止这种情况发生的最佳做法也将受到赞赏。

4 个答案:

答案 0 :(得分:1)

这可能是由于_ each函数中的一些魔法所致,因为我怀疑它同时接受ObjectArray s ...制作属于自己的函数?< / p>

简单实施(避免一些常见的陷阱):

function each(obj, map_func) {
    var key;
    for (key in obj) {
        if (Object.prototype.hasOwnerProperty.call(obj, key)) {
            map_func(key, obj[key]);
        }
    }
}

_的{​​{1}}中的魔力可能是由于JavaScript中的一种令人讨厌的“习惯”,即“看起来像阵列”但实际上并不是数组,就像魔法变量{{ 1}},我认为在选择的DOM元素中也是each

答案 1 :(得分:1)

我无法想到任何替代它的东西。我想使用length属性是一种鸭子类型,它将jQuery标记为可迭代。

但是..你可以不使用 jQuery的每种方法,并以手动方式进行..

只需使用

for (key in product) { 


}

你得到了你的基本循环。现在,如果您可能覆盖对象的原型,还应检查product.hashOwnProperty(key)以确保在产品实例中定义了您正在迭代的当前键。

现在如果你还需要一个新的闭包范围,那也很简单..这里是每个函数的另一种选择..

var myEach = function(subject, callback) {

  for (key in subject) {

     if (subject.hasOwnProperty(key)) {
        callback(subject[key], key);
     }
  }

}

注意:未经测试。

答案 2 :(得分:1)

试试这个:

    var product = {
        name: "MacBook Pro 15 Inch",
        description: 'The new macbook pros....',
        length: 15,
        height: 15,
        weight: 4
    };
    console.log('Product has the following properties');
    _.each(_.keys(product), function(key){
        console.log(key + ":" + product[key]);
    });

答案 3 :(得分:1)

如果您无法更改长度属性的名称,可以在下划线中添加额外的检查以防止出现这种情况:

_.each = _.forEach = function(obj, iterator, context) {
  if (obj == null) return;
  if (Array.prototype.forEach && obj.forEach === Array.prototype.forEach) {
    obj.forEach(iterator, context);
  } else if (obj.length === +obj.length && obj.constructor != Object) {
    for (var i = 0, l = obj.length; i < l; i++) {
      if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
    }
  } else {
    for (var key in obj) {
      if (_.has(obj, key)) {
        if (iterator.call(context, obj[key], key, obj) === breaker) return;
      }
    }
  }
};

此处的添加是第5行的&& obj.constructor != Object。虽然monkeypatching下划线可能不是世界上最令人向往的东西。但

编辑:实际上,这会打破像arguments这样的伪数组,因为它的构造函数是Object,但<an array-like object>.hasOwnProperty(<an integer>)是假的。 Woo JavaScript。