On Dec 8, 2009, at 10:10 AM, Mike Samuel wrote:
1) Does the object have the special semantics around .length? This
is
potentially useful to know and the normal way to find out doesn't
work. Instanceof is affected by setting __proto__, yet the special
.length handling persists and instanceof doesn't work for cross-
iframe
objects.
I think I agree with the bit about length, but __proto__ doesn't work
on non mozilla interpreters
WebKit JSC implemented too :-/.
and isn't likely to be standardized.
You got that part right :-).
I don't see how it's relevant to array-like-ness.
Agreed, but Erik's point here was about instanceof. Not only mutable
__proto__, but mutable bindings for constructors, and the issue of
multiple global objects with their unrelated suites of builtin
constructors, make instanceof less than ideal for deciding "array-like".
Efficiency is obviously important, but another important distinction
is whether 'length' should be included in the set of keys iterated
over,
In ES1-5, length is not enumerable for Array, String, and arguments
objects. Anything array-like, same deal or it's not "like" enough.
and whether iteration over array-index keys should be in numeric
order.
I'm suspicious of real code depending on insertion order. Typically
arrays are built front to back so the two are the same. Exceptional
cases may break existing for-in loops that inspect arrays and want
numeric order. This is something to investigate (google codesearch?).
But really for..in is pretty sick for arrays. It will convert every
single index in the array to a string. That's not something to be
encouraged IMHO.
Also agreed.
Yes, that is an ES1 change from my Netscape implementation. It is
costly enough that optimizing implementations use memoized or static
strings for small integer literals!
Yet for-in on an array-like is attractive, especially in light of
comprehensions and generator expressions. One way forward would be to
change to number type under opt-in Harmony versioning. Another option
is new syntax, but that requires opt-in versioning anyway, and it's
not clear to me that changing for-in on Arrays, or on all array-likes,
to return numbers for indexes, is an incompatibility that we could not
"get away with".
If anyone knows of real-world code that would be broken by the type of
the for-in loop variable not always being string, I'm all ears.
/be
--
Erik Corry
Prototype.js dodges this problem by adding an each method to
Array.prototype and others. This obviously fails for cross-context
Arrays, and also suffers from the large sparse array and missing
non-array-index properties problems.
It does switch on arrays in places, and does so inconsistently though
-- in one case (unnecessarily?) filtering out arguments objects?
if (Object.isArray(item) && !('callee' in item)) {
for (var j = 0, arrayLength = item.length; j < arrayLength; j+
+)
array.push(item[j]);
} else {
function flatten() {
return this.inject([], function(array, value) {
if (Object.isArray(value))
return array.concat(value.flatten());
array.push(value);
return array;
dojo.clone does
if(d.isArray(o)){
r = [];
for(i = 0, l = o.length; i < l; ++i){
if(i in o){
r.push(d.clone(o[i]));
}
}
}else{
// generic objects
r = o.constructor ? new o.constructor() : {};
}
dojo.isArray = function(/*anything*/ it){
// summary:
// Return true if it is an Array.
// Does not work on Arrays created in other
windows.
return it && (it instanceof Array || typeof it == "array"); //
Boolean
}
dojo.isArrayLike = function(/*anything*/ it){
// summary:
// similar to dojo.isArray() but more permissive
// description:
// Doesn't strongly test for "arrayness". Instead, settles for
"isn't
// a string or number and has a length property".
Arguments objects
// and DOM collections will return true when
passed to
// dojo.isArrayLike(), but will return false when
passed to
// dojo.isArray().
// returns:
// If it walks like a duck and quacks like a duck,
return `true`
return it && it !== undefined && // Boolean
// keep out built-in constructors (Number, String, ...) which
have length
// properties
!d.isString(it) && !d.isFunction(it) &&
!(it.tagName && it.tagName.toLowerCase() == 'form') &&
(d.isArray(it) || isFinite(it.length));
}
and dojo uses these definitions to do type coercion
}else if(!dojo.isArray(content)){
//To get to this point, content is array-like,
but
//not an array, which likely means a DOM
NodeList. Convert it now.
content = dojo._toArray(content);
The closure library similarly defines both isArray and isArrayLike,
but with differences (
http://code.google.com/p/closure-library/source/browse/trunk/closure/goog/base.js
):
goog.isArrayLike = function(val) {
var type = goog.typeOf(val);
return type == 'array' || type == 'object' && typeof val.length
== 'number';
};
which is then used in many places (
http://www.google.com/codesearch?q=goog.isArrayLike+package%3Ahttp%3A%2F%2Fclosure-library%5C.googlecode%5C.com&origq=goog.isArrayLike
), e.g. in iter.js
goog.iter.forEach = function(iterable, f, opt_obj) {
if (goog.isArrayLike(iterable)) {
MooTools is the only library I looked at that does not check
array-likedness. They do something similar to prototype by
monkey-patching Array, which will fail for cross-context arrays. They
do extend the concept of length to their Hash class:
getLength: function(){
var length = 0;
for (var key in this){
if (this.hasOwnProperty(key)) length++;
}
return length;
}
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss