JavaScript中的哪些对象具有.length属性? (又名为什么Underscore _.each将我的函数对象视为数组?) [英] Which Objects in JavaScript have a .length property? (aka Why does Underscore _.each treat my Function Object like an Array?)

查看:72
本文介绍了JavaScript中的哪些对象具有.length属性? (又名为什么Underscore _.each将我的函数对象视为数组?)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直认为只有 Array 对象才有 .length 属性。但是,我再次看到提到阵列式的对象。我没有调查过这个,现在看来我对JS中这个话题的无知可能会让我陷入困境。例证:

I've been under the impression that only Array objects have a .length property. But, then again, I've also seen mentions of objects that are "array-like". I've not looked into this, and now it seems like my ignorance of this topic in JS may be biting me in the ass. Case in point:

我有以下代码:

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

_.extend(View, Backbone.Events, {

    make_children: function(parent) {
      // code
    }

});

稍后,我使用此查看 函数使用Underscore的 _。每个,它决定这个函数对象是一个数组,因为它有一个 .length property:

Later on, I use this View Function with Underscore's _.each, which decides this function object is an array, because it has a .length property:

// 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 是一个整数索引,实际上并没有在我的<$上定义c $ c> obj 查看。确切地说,在上面的代码中, obj [0] undefined obj。长度=== + obj.length true obj.length 1 。这里发生了什么?

This results in code that doesn't work, because obj[i] where i is an integer index, is not actually defined on my obj View. To be precise, in the above code, obj[0] is undefined while obj.length === +obj.length is true and obj.length is 1. What's going on here?

附录

Underscore的主要维护人员说以下内容 https://github.com/documentcloud/underscore/pull/510

Underscore's chief maintainer says the following on https://github.com/documentcloud/underscore/pull/510:


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

Simply making each reject function objects doesn't really help. We've made a conscious decision to use a numerical length property to detect array-like objects.

相反,不要传递函数对象每个

Instead, don't pass function objects to each.

附录2

意识到由于我无法将函数对象传递给 _。每个,我只能投了它像这样的常规对象:

Realized that since I couldn't pass a function object to _.each, I could just "cast it" to a regular object like so:

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


推荐答案

这里的问题是 underscore.js ,就像 jquery 一样,都使用 .length 属性作为标志在他们的每个函数中。当存在 length 属性时,该函数假定传递的参数可以通过正常的for循环进行迭代。这个逻辑背后的原因是期望当定义 length 属性时,可以按顺序遍历参数 ,这是为什么使用for循环。

The issue here is that underscore.js, much like jquery, both use the .length property as a flag in their each functions. When the length property is present, the function assumes that the argument passed can be iterated through with a normal for loop. The reason behind this logic is there is an expectation that when the length property is defined then it is possible to iterate through the argument in order which is why the for loop is used.

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

The result of misusing length is essentially a name collision where there is an unintended result. I would suggest changing length to another synonym such as size or capacity or totalViews, etc.

编辑

如果没有其他替代供您使用,并且您必须有长度,同时仍保留 _。每个的功能,然后你可以稍微破解它。此插件适用于下划线版本1.4.3的缩小版本。

If there are no other alternatives for you to use, and you must have length in there while still retaining _.each's functionality, then you can slightly hack it. This plug works with the minified version of underscore version 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/

它的作用基本上是使用 forEach length 属性存在但 typeof(yourObject [0])==undefined时。

Basically what it does is use forEach when the length property exists but typeof(yourObject[0]) == "undefined".

这篇关于JavaScript中的哪些对象具有.length属性? (又名为什么Underscore _.each将我的函数对象视为数组?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆