我发现自己处于一个有趣的境地。我使用对象文字来表示现实世界中的产品。现在每个产品都有与其相关的长度以用于运输目的。它看起来像这样:
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
循环,所以循环永远不会被执行。
现在提出问题,如何防止覆盖长度属性?防止这种情况发生的最佳做法也将受到赞赏。
答案 0 :(得分:1)
这可能是由于_
each
函数中的一些魔法所致,因为我怀疑它同时接受Object
和Array
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。