私は、Array
オブジェクトだけが.length
プロパティを持っているという印象を受けてきました。しかし、繰り返しになりますが、「配列のような」オブジェクトについての言及も見ました。私はこれを調べていませんが、JSでこのトピックを知らないことが、私を尻に食い込ませているようです。適例:
私は次のコードを持っています:
var View = function(options) {
// code
};
_.extend(View, Backbone.Events, {
make_children: function(parent) {
// code
}
});
後で、これView
Function
をアンダースコアで使用します。アンダースコアは、次のプロパティ_.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]
はundefined
whileobj.length === +obj.length
でありtrue
、obj.length
is1
です。何が起きてる?
補遺
Underscoreのチーフメンテナーは、https: //github.com/documentcloud/underscore/pull/510で次のように述べています。
それぞれのreject関数オブジェクトを作成するだけでは、実際には役に立ちません。配列のようなオブジェクトを検出するために数値の長さプロパティを使用することを意識的に決定しました。
代わりに、関数オブジェクトをに渡さないでください
each
。
補遺2
関数オブジェクトをに渡すことができなかった_.each
ので、次のように通常のオブジェクトに「キャスト」できることに気づきました。
var regular_obj = _.extend({}, View);