4

我一直认为只有Array对象才有.length属性。但是,话又说回来,我还看到提到“类似数组”的对象。我还没有研究过这个,现在看来我对 JS 中这个话题的无知可能会咬我的屁股。一个例子:

我有以下代码:

var View = function(options) {
  // code
};

_.extend(View, Backbone.Events, {

    make_children: function(parent) {
      // code
    }

});

稍后,我将它View Function与 Underscore 一起使用_.each,它决定这个函数对象是一个数组,因为它有一个.length属性:

// Code from Underscore.js's `_.each`:
} else if (obj.length === +obj.length) { // This is true
  for (var i = 0, l = obj.length; i < l; i++) { // **So, execution goes here**
    if (iterator.call(context, obj[i], i, obj) === breaker) return
  }
} else {
  for (var key in obj) {
    if (_.has(obj, key)) { // **Execution does __not__ go here**
      if (iterator.call(context, obj[key], key, obj) === breaker) return;
    }
  }
}

这导致代码不起作用,因为整数索引obj[i]在哪里i实际上并没有在我的obj View. 准确地说,在上面的代码中,obj[0]is undefinedwhile obj.length === +obj.lengthistrueobj.lengthis 1。这里发生了什么?

附录

Underscore 的首席维护者在https://github.com/documentcloud/underscore/pull/510上说:

简单地制作每个拒绝函数对象并没有真正的帮助。我们有意识地决定使用数值长度属性来检测类似数组的对象。

相反,不要将函数对象传递给each.

附录 2

意识到由于我无法将函数对象传递给_.each,因此我可以将其“强制转换”为常规对象,如下所示:

var regular_obj = _.extend({}, View);
4

2 回答 2

5

Which Objects in JavaScript have a .length property?

By oh-so-tautological definition, any object which has a length property.

This happens to include functions.

length is a property of a function object, and indicates how many arguments the function expects, i.e. the number of formal parameters.

This is also array-like, because it has a length:

var foo = {
    bar: true,
    baz: 'quux',
    length: 42
}
于 2013-03-18T23:18:52.343 回答
5

这里的问题是underscore.js,很像,两者都在其函数中jquery使用该.length属性作为标志。each当该length属性存在时,该函数假定传递的参数可以使用普通的 for 循环进行迭代。这种逻辑背后的原因是期望在length定义属性时可以按顺序迭代参数,这就是使用 for 循环的原因。

滥用的结果length本质上是名称冲突,其中存在意外结果。我建议更改length为另一个同义词,例如sizeor capacityortotalViews等​​。


编辑

如果没有其他替代品可供您使用,并且您必须在其中保留长度,同时仍保留_.each's 的功能,那么您可以稍微破解它。此插件适用于下划线版本 1.4.3 的缩小版

var s = Array.prototype.ForEach;
var r = {};
var myEach = function (n,t,e){if(null!=n)if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length&&typeof(n[0])!="undefined"){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a in n)if(_.has(n,a)&&t.call(e,n[a],a,n)===r)return};
_.each=myEach;

这是一个演示:http: //jsfiddle.net/Xa5qq/

基本上它的作用是forEachlength属性存在但typeof(yourObject[0]) == "undefined".

于 2013-03-18T23:35:10.463 回答