0

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

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。为什么?好吧,因为内部下划线使用长度属性,所以 Javascript 中的每个对象都必须遍历传入对象的所有属性。由于我们覆盖了那个值,它现在是-1,并且由于我们从 开始循环i = 0,循环将永远不会被执行。

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

4

4 回答 4

1

这可能是由于_'seach函数中的一些魔法,因为我怀疑它同时接受Objects 和Arrays .. 自己制作?

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

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

_'s中的魔力each可能是由于 JavaScript 中有一个讨厌的“习惯”,即拥有“看起来”像数组但实际上不是数组的东西,就像魔法变量一样arguments,我认为options在选择 DOM 元素中也是如此。

于 2012-07-10T23:45:14.950 回答
1

我想不出任何可以覆盖它的副手。我想使用 length 属性是一种鸭子类型,它被 jQuery 标记为可迭代。

但是..你不能使用jQuery each 方法,而是手动进行..

通过简单地使用

for (key in product) { 


}

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

现在,如果您还需要一个新的闭包范围,那也很简单.. 这是每个函数的替代方法..

var myEach = function(subject, callback) {

  for (key in subject) {

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

}

注:未经测试。

于 2012-07-10T23:47:30.357 回答
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]);
    });
于 2012-07-10T23:49:31.817 回答
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;
      }
    }
  }
};

这里添加的是第&& obj.constructor != Object5 行。它有效,尽管猴子补丁下划线可能不是世界上最理想的东西。

编辑:实际上,这在伪数组上中断arguments,因为它的构造函数是Object,但是<an array-like object>.hasOwnProperty(<an integer>)是假的。哇 JavaScript。

于 2012-07-10T23:56:48.757 回答