I got an interesting question and maybe some of you might have idea or
at least want to have some riddle to solve... whatever. I would like
to create own Object that would behave similar to Array Object, but
would have defined some methods that are not in current Array
implementation. It need to not touch .prototype of an Array, so it
should work like this:
var a = [2,4,6];
a.someAddedFunction(); // error - no Array .prototype extending
var c = new SuperArray([2,4,6]);
for (var i=0,l=c.length;i<l;i++)
{
alert(c[i]); // alerts 2, then 4, then 6
}
c.someAddedFunction(); // calls function
Have you got any idea how to do that? Is this possible at all? Thanks
for any answers here.
Try:
Hello NG,
> I got an interesting question and maybe some of you might have idea or
> at least want to have some riddle to solve... whatever. I would like
> to create own Object that would behave similar to Array Object, but
> would have defined some methods that are not in current Array
> implementation.
You cannot add a method to the array in it's strict sense,
but to the object that it is as well.
> It need to not touch .prototype of an Array, so it
> should work like this:
>
> var a = [2,4,6];
>
> a.someAddedFunction(); // error - no Array .prototype extending
No error here if you do:
var a = [2,4,6];
a.fx = function(n){return this[n]};
alert( a.fx(1) ); // 4
Chrome tested.
--
Evertjan.
The Netherlands.
(Please change the x'es to dots in my emailaddress)
Much of the behaviour of an Array in javascript codes from its special
[[Put]] method (which has special handling for 'array index' and -
length - property names), this method cannot be inherited through a
prototype chain or transferred between objects so an object that
behaves like an Array is probably going to have to be an Array, though
possibly a modified one.
> but would have defined some methods that are not in current
> Array implementation.
So what might be called an 'extended array'.
>It need to not touch .prototype of an Array, so it
Good. That reduces your options to creating array instances and
assigning functions to their named properties to provide additional
method (and not using for-in loops on those object, or filtering the
for-in loops used so they don't act on the added methods).
> should work like this:
>
> var a = [2,4,6];
>
> a.someAddedFunction(); // error - no Array .prototype extending
>
> var c = new SuperArray([2,4,6]);
//Order of execution matters here.
var getSuperArrayInstance = (function(){
function forSomeAddedFunction(){
// Code that can use - this - to refer to the array (itself).
}
return (function(array){
/* This could either modify the array argument or return a new
array that is a copy of the original array. Here only the
former will be done.
*/
/*Next a reference to a (by now) existing function is assigned
to a named property of the array passed in, giving it an
additional method.
*/
array.someAddedFunction = forSomeAddedFunction;
/* The modified array is returned. Essential if an internally
created copy of the original array had been used but
possibly not required if this function's task is only to
add a new interface to an object passed in.
*/
return array;
});
})():
var c = getSuperArrayInstance([2,4,6]);
> for (var i=0,l=c.length;i<l;i++)
> {
> alert(c[i]); // alerts 2, then 4, then 6
>
> }
>
> c.someAddedFunction(); // calls function
>
> Have you got any idea how to do that?
As above, and variations on the theme.
> Is this possible at all?
Up to a point, that satisfies practical requirements.
> Thanks for any answers here.
Richard.
I've never seen anyone else wrapping function expression in return
statements with parentheses. Are there any environments that fail
otherwise or is this a convention/habit?
> /* This could either modify the array argument or return a new
> array that is a copy of the original array. Here only the
> former will be done.
> */
> /*Next a reference to a (by now) existing function is assigned
> to a named property of the array passed in, giving it an
> additional method.
> */
> array.someAddedFunction = forSomeAddedFunction;
> /* The modified array is returned. Essential if an internally
> created copy of the original array had been used but
> possibly not required if this function's task is only to
> add a new interface to an object passed in.
> */
> return array;
> });
> })():
[...]
--
kangax
I am not aware of any problematic environments, I am just in the habit
of wrapping expressions that get returned in parenthesise if they are
anything but the simplest expressions, and muti-line function
expressions certainly do not qualify as simple expressions.
Richard.
Isn't it possible (by any means other than Array.prototype or
Object.protoype) to force an [] to *inherit* .someAddedMethod() ?
There's no way to insert an additional object in its prototype chain ?
--
Jorge.
There's no way to inherit "special" [[Put]]. That's the actual "problem"
here.
[...]
--
kangax
Yes yes I understand that. But if you could insert an additional
object (with the .someAddedMethod()) in the prototype chain of an [],
you wouldn't need to add any own properties in order to convert it
into a superArray instance...
--
Jorge.
Oh, you mean something like this?
var arr = [1,2,3];
arr.__proto__ = {
last: function() {
return this[this.length-1];
},
__proto__: Array.prototype
};
arr.last(); // 3
arr.push('foo');
arr.length; // 4
--
kangax
:-)
but can't use __proto__ ... : an Array.create(prototypeObject).
--
Jorge.
What's `Array.create`?
I actually don't see why you would want to have method in proto chain of
an object instead of just assigning that method to an object directly.
Latter one is simpler and much more compatible.
--
kangax
If at all possible, it ought to be like Crockford's Object.create
(prototypeObject); but for Arrays: something like this:
Array.create= function (o) {
function f () { return []; }
f.prototype= o;
return new f();
}
that works (unlike this).
> I actually don't see why you would want to have method in proto chain of
> an object instead of just assigning that method to an object directly.
Because that's what inheritance is there for: to share a single method
among all the instances of a class.
Why not in Array.prototype ?
Because that would turn each and every Array into an instance of
superArray.
Why not to augment instead ?
Because we've got inheritance for a reason: this reason.
> Latter one is simpler and much more compatible.
In the pre-ES5 era, yes.
--
Jorge.
BTW, it's not that I don't like what Cronford has written.
--
Jorge.
No, it is the post ES 3 era in which the latter is not more
compatible. Currently we are only in the post ES 2 era (where try-
catch became tolerable, if not actually that useful).
Richard.
> var arr = [1,2,3];
>
> arr.__proto__ = {
> last: function() {
> return this[this.length-1];
> },
> __proto__: Array.prototype
> };
>
> arr.last(); // 3
> arr.push('foo');
>
> arr.length; // 4
For a sensible test, that needs to be arr.last() == "foo";
PointedEars
--
var bugRiddenCrashPronePieceOfJunk = (
navigator.userAgent.indexOf('MSIE 5') != -1
&& navigator.userAgent.indexOf('Mac') != -1
) // Plone, register_function.js:16
But less memory efficient with more than one instance.
> and much more compatible.
Only if you use __proto__.
PointedEars
--
Prototype.js was written by people who don't know javascript for people
who don't know javascript. People who don't know javascript are not
the best source of advice on designing systems that use javascript.
-- Richard Cornford, cljs, <f806at$ail$1$8300...@news.demon.co.uk>
> I got an interesting question and maybe some of you might have idea or
> at least want to have some riddle to solve... whatever. I would like
> to create own Object that would behave similar to Array Object, but
> would have defined some methods that are not in current Array
> implementation. It need to not touch .prototype of an Array, so it
> should work like this:
>
> var a = [2,4,6];
>
> a.someAddedFunction(); // error - no Array .prototype extending
When i define helper methods for arrays, i never use Array.prototype
to add new properties. I want to keep clear for-in, because every
third party properties added to `object' referred from Array.prototype
doesn't haves property {DontEnum}.
Approach like that:
var a = new Array();
a.someAddedFunction = function(){};
Here `a' referred `object' created from Array.[[Construct]] method. In
the next line, will be added property `someAddedFunction' to that
`object' and assigned reference to function. That property doesn't
have {DontEnum}, so will be enumerated from for-in loop. Not only
this. If you use Richard Cornford pattern, on the every `object'
passed for argument, will be added new properties on thy fly and
assigned value to that properties. That is more memory unefficient,
and that properties doesn't haves {DontEnum} attribute.
If you want, you can use `object' referred from property of Global
Object `Array', to defined helper methods and passed reference to
`object' who internal [[Prototype]] refer Array.prototype.
e.g.
Array.someAddedFunction = function(arr){};
Disadvantage of that technique is value of argument `arr'. You might
need to checked value. Because you don't sure that value is reference
to `object' who [[Prototype]] referred Array.prototype.
Regards.
Hmmm, true.
So something like this then? (after feature-testing __proto__ behavior,
of course):
var augment = (function(){
var mixin = {
last: function() {
return this[this.length-1];
},
__proto__: Array.prototype
};
return function(object) {
object.__proto__ = mixin;
return object;
};
})();
var arr = augment([1,2,3]);;
arr.last(); // 3
arr.push('foo');
arr.last(); // "foo"
arr.length; 4
var arr2 = augment([1,2,3,4,5]);
arr2.push('bar');
arr2.last(); // "bar"
arr2.length; // 6
(in FF3.5.3)
>
>> and much more compatible.
>
> Only if you use __proto__.
How else can you assign to object's [[Prototype]]?
--
kangax
> Thomas 'PointedEars' Lahn wrote:
>> kangax wrote:
>>> I actually don't see why you would want to have method in proto chain of
>>> an object instead of just assigning that method to an object directly.
>>>
>>> Latter one is simpler
>>
>> But less memory efficient with more than one instance.
>
> Hmmm, true.
>
> So something like this then? (after feature-testing __proto__ behavior,
> of course):
>
> var augment = (function(){
> var mixin = {
> last: function() {
> return this[this.length-1];
> },
> __proto__: Array.prototype
> };
> return function(object) {
> object.__proto__ = mixin;
> return object;
> };
> })();
>
> var arr = augment([1,2,3]);
> [...]
Not really, see below.
>>> and much more compatible.
>>
>> Only if you use __proto__.
>
> How else can you assign to object's [[Prototype]]?
In most cases, a standards-compliant reference to the object's prototype
object is known; in this case, `Array.prototype'. In fact, I do not think
there is much value in replacing the prototype object of Array instances
with an object that has the original value of `Array.prototype' next in its
prototype chain. The only advantage of this approach that I can think of is
that properties inherited from Array.prototype could be shadowed without
overwriting them.
> On 27 Окт, 14:01, wilq <wil...@gmail.com> wrote:
>> I got an interesting question and maybe some of you might have idea or
>> at least want to have some riddle to solve... whatever. I would like
>> to create own Object that would behave similar to Array Object, but
>> would have defined some methods that are not in current Array
>> implementation. It need to not touch .prototype of an Array, so it
>> should work like this:
>>
>> var a = [2,4,6];
>>
>> a.someAddedFunction(); // error - no Array .prototype extending
>
> When i define helper methods for arrays, i never use Array.prototype
> to add new properties. I want to keep clear for-in, because every
> third party properties added to `object' referred from Array.prototype
> doesn't haves property {DontEnum}.
That reasoning is questionable, though. Why are you using a `for-in'
statement to iterate over Array instances to begin with?
> Approach like that:
> var a = new Array();
> a.someAddedFunction = function(){};
That is OK for one instance, but if you have a number of instances you would
waste a lot of memory with that approach. That could be mitigated with
creating the function only once and only assign a reference to it, but it
would be comparably tedious anyway. I am not sure if for-in is worth all
that.
> [...]
> If you want, you can use `object' referred from property of Global
> Object `Array', to defined helper methods and passed reference to
> `object' who internal [[Prototype]] refer Array.prototype.
> e.g.
> Array.someAddedFunction = function(arr){};
>
> Disadvantage of that technique is value of argument `arr'. You might
> need to checked value. Because you don't sure that value is reference
> to `object' who [[Prototype]] referred Array.prototype.
The argument is unnecessary for operating on one Array instance; the
function can use `this', regardless to which property a reference to it is
assigned at first. Having the object referred to by `Array' as a repository
of possible prototype methods is an interesting idea, theoretically; I am
just not sure of how much practical use that would be.
PointedEars
--
realism: HTML 4.01 Strict
evangelism: XHTML 1.0 Strict
madness: XHTML 1.1 as application/xhtml+xml
-- Bjoern Hoehrmann
Perhaps, you should read this thread again more carefully?
--
kangax
> Thomas 'PointedEars' Lahn wrote:
>> kangax wrote:
>>> Thomas 'PointedEars' Lahn wrote:
>>>> kangax wrote:
>>>>> I actually don't see why you would want to have method in proto chain
>>>>> of an object instead of just assigning that method to an object
>>>>> directly.
>>>>>
>>>>> Latter one is simpler
>>> [...]
>>>>> and much more compatible.
>>>> Only if you use __proto__.
>>> How else can you assign to object's [[Prototype]]?
>>
>> In most cases, a standards-compliant reference to the object's prototype
>> object is known; in this case, `Array.prototype'. In fact, I do not
>> think there is much value in replacing the prototype object of Array
>> instances with an object that has the original value of `Array.prototype'
>> next in its prototype chain. The only advantage of this approach that I
>> can think of is that properties inherited from Array.prototype could be
>> shadowed without overwriting them.
>
> Perhaps, you should read this thread again more carefully?
Or perhaps you should?
As I understand it, this thread is about creating an object that works like
an Array instance but has additional features. Because the [[Put]] method
of Array instances cannot be inherited (your push() tests the wrong
property), that can only be accomplished with a true Array instance, and
there are two ways to provide it with new properties: a) augment the object
itself; b) augment its prototype object so that those properties are
inherited. As for b), [].__proto__ === Array.prototype, so using the less
compatible `__proto__' property is unnecessary. (The same goes for user-
defined objects, for which the prototype object can be referred to by either
Object.prototype or usually UserDefinedConstructor.prototype.) There is
also little value in the extended prototype chain that you proposed as the
method can easily be added to that Array prototype directly. (It is all the
same to for-in iteration.)
There is a c) which has not been mentioned in this thread yet (but we've
been over this): Use a wrapper object, and map properties inherited from the
Array prototype accordingly.
PointedEars
--
Danny Goodman's books are out of date and teach practices that are
positively harmful for cross-browser scripting.
-- Richard Cornford, cljs, <cife6q$253$1$8300...@news.demon.co.uk> (2004)
It was already answered not long time ago:
http://groups.google.com/group/comp.lang.javascript/msg/17ca24e86760231b
Are you sure you haven't missed anything?
"I would like to create own Object that would behave similar to Array
Object, but would have defined some methods that are not in current
^^^^^^^^^^^^^^
Array implementation. It need to not touch .prototype of an Array, so it
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
should work like this"
>
> As I understand it, this thread is about creating an object that works like
> an Array instance but has additional features. Because the [[Put]] method
> of Array instances cannot be inherited (your push() tests the wrong
> property), that can only be accomplished with a true Array instance, and
Why wrong property? Doesn't `push` affect array object's `length`?
[...]
> There is a c) which has not been mentioned in this thread yet (but we've
> been over this): Use a wrapper object, and map properties inherited from the
> Array prototype accordingly.
Of course :)
--
kangax
> That reasoning is questionable, though. Why are you using a `for-in'
> statement to iterate over Array instances to begin with?
Where is the wrong here? For-in is build in iterator. Iterate over any
properties of `object' who doesn't have attribute {DontEnum}. Decimal
indexes of array object itself is a properties of that object.
When i open PrototypeJS lib API, to Array object.
<URL:http://api.prototypejs.org/language/array.html />
<quote>
Why you should stop using for...in to iterate?
</quote>
Please anybody, explain why, because in url above, explanation is
related with PrototypeJS implementation of array add-on methods.
> [...]
> Good. That reduces your options to creating array instances and
> assigning functions to their named properties to provide additional
> method (and not using for-in loops on those object, or filtering the
> for-in loops used so they don't act on the added methods).
> [...]
And what's the main goal do not extend Array.prototype if you still
avoid for-in loops for you single in-place extended objects?
for-in loop is only useful for sparse arrays (better - very sparse
arrays, with indexes: 0, 1, 99, 502) and for such structures better to
use Object (without afraid for-in loops as no one in good sense will
extend Object.prototype).
But anyway, the wrapper you created has enumerable [.last] method.
What's the main goal to afraid Array.prototype itself in this case if
still for-in loops will affect on your wrapped object properties?
>
> Why wrong property? Doesn't `push` affect array object's `length`?
>
> [...]
>
[.push] can affect `length` property and without wrappers:
var o = {
push: [].push
};
o.push(1);
o.length; // 1
But sure in this case `length` will be enumerable and seen in for-in.
P.S.> Who said "do not extend Array.prototype"? As all this stuff with
in-place adding methods to array single objects or with wrappers -
will show that added methods in for-in? So you should still "afraid"
of for-in. Why do not extend Array.prototype then if needed?
If the only reason - "we don't know who will use our library, so we
won't extend Array.prototype that they can use for-in for arrays" -
that's ok, that's another question, I agree in here. But in own
project - I don't see any troubles for do not augment Array.prototype.
Only if you iterate strong sparse arrays, but for that better to use
non-array object.
Because it iterates over object properties, not over array members.
The difference may be not visible or important:
var a = new Array(10);
a[10] = 'foo';
a['foo'] = 'bar';
for (var p in a) {
window.alert(
'Properties\n'+
p+'='+a[p]);
}
for (var i=0; i<a.length; a++) {
window.alert(
'Array members\n'+
'a['+i+']='+a[i]);
}
Because JavaScript is sparse, some programmers are using for-in
instead of for(length) to skip unnecessary loops in case if say only
1st and 1000th array elements are assigned. I don't think it is really
cool. In the controllable by me environment it is strictly prohibited,
but of course I don't dare to extent in-office rules worldwide. I
still believe that the broth has to be made in a casserole and the
omelet in the frying pan, even if technically it is possible do do it
in the opposite way if the frying pan is deep enough and the casserole
is hit resistant enough. Same applies to Object instances and Array
instances and for-in vs for(length). IMHO.
So the thread has drifted a bit. Your approach touches ".prototype of an
Array", too. That you are using `__proto__' to refer to said object
instead, does not change that.
>> As I understand it, this thread is about creating an object that works
>> like an Array instance but has additional features. Because the [[Put]]
>> method of Array instances cannot be inherited (your push() tests the
>> wrong property), that can only be accomplished with a true Array
>> instance, and
>
> Why wrong property? Doesn't `push` affect array object's `length`?
It does, but the array-ness of an object referred to by `o' is defined by an
assignment to o[i], with `i' being the equivalent to an unsigned 32-bit
integer value, to change the value of o.length if o.length was previously
smaller than i+1 (see ES3F, 15.4). Indeed, Array.prototype.push() is one of
the "intentionally generic" methods, so it can work with any object that
provides read access to a `length' property (see ES3F, 15.4.4.7.)
PointedEars
--
Use any version of Microsoft Frontpage to create your site.
(This won't prevent people from viewing your source, but no one
will want to steal it.)
-- from <http://www.vortex-webdesign.com/help/hidesource.htm> (404-comp.)
> Thomas 'PointedEars' Lahn wrote:
>> That reasoning is questionable, though. Why are you using a `for-in'
>> statement to iterate over Array instances to begin with?
>
> Where is the wrong here? For-in is build in iterator. Iterate over any
> properties of `object' who doesn't have attribute {DontEnum}. Decimal
> indexes of array object itself is a properties of that object.
>
> When i open PrototypeJS lib API, to Array object.
> <URL:http://api.prototypejs.org/language/array.html />
>
> <quote>
> Why you should stop using for...in to iterate?
> </quote>
Why, Prototype.js is junk anyway.
> Please anybody, explain why, because in url above, explanation is
> related with PrototypeJS implementation of array add-on methods.
VK has already provided the correct explanation, except of the part below
the source code, which consists of guesswork and fantasy again.
The goal is not in the OP, just the requirement to avoid modifying
Array.prototype. There is still no need to avoid for-in on these new
objects, just the likelihood that the values will need to be filtered if
it is used on them. Then again it may be entirely feasible to avoid
for-in on these objects while leaving it available for ordinary Arrays.
> for-in loop is only useful for sparse arrays (better - very
> sparse arrays, with indexes: 0, 1, 99, 502) and for such
> structures better to use Object (without afraid for-in loops
> as no one in good sense will extend Object.prototype).
Yes, we have never known whether the use of for-in has any relevance for
this object at all. I just mentioned because its use is impacted by any
viable strategy adopted and it makes sense to be aware of that up-front.
Richard.
Well, I'm not the one asking for it, so I wouldn't know real intentions
;) Probably to avoid augmenting "public" Array, and so reducing
conflicts with 3rd party code.
>
>> Why wrong property? Doesn't `push` affect array object's `length`?
>>
>> [...]
>>
>
> [.push] can affect `length` property and without wrappers:
>
> var o = {
> push: [].push
> };
> o.push(1);
> o.length; // 1
You're right. Bad test on my part.
[...]
Doesn't OP example make it clear what was meant by "touches"? If I
understood it right, the snippet with __proto__ setting doesn't "touch"
`Array.prototype`.
>
>>> As I understand it, this thread is about creating an object that works
>>> like an Array instance but has additional features. Because the [[Put]]
>>> method of Array instances cannot be inherited (your push() tests the
>>> wrong property), that can only be accomplished with a true Array
>>> instance, and
>> Why wrong property? Doesn't `push` affect array object's `length`?
>
> It does, but the array-ness of an object referred to by `o' is defined by an
> assignment to o[i], with `i' being the equivalent to an unsigned 32-bit
> integer value, to change the value of o.length if o.length was previously
> smaller than i+1 (see ES3F, 15.4). Indeed, Array.prototype.push() is one of
> the "intentionally generic" methods, so it can work with any object that
> provides read access to a `length' property (see ES3F, 15.4.4.7.)
Thanks. You're absolutely right. Should have used property accessor instead.
--
kangax
I order to create a "newClass" of [] you shouldn't augment
Array.prototype as that would automatically convert each and every
existing and future instance of [] into an instance of "newClass".
If you wanted to create two different classes of [], each with a
different .foo() method, augmenting Array.prototype would not work
either.
Augmenting Array.prototype would not work either if you wanted
"newClass" to override an existing Array.prototype method.
So, in order to leave existing instances as they are and be able to
create not one but as many different classes of [] as you wish, you
could either augment each individual instance manually which is what
Richard did, or attempt to use inheritance by inserting the class
prototype objects in the prototype chains of the class instances,
which is what kangax was doing, and I was wondering whether __proto__
is the only way to achieve it.
--
Jorge.
> [...]
> with `i' being the equivalent to an unsigned 32-bit
> integer value
Not an integer, but converted to string (as property names of any
object - only strings).
> Thomas 'PointedEars' Lahn wrote:
>> [...]
>> with `i' being the equivalent to an unsigned 32-bit
>> integer value
>
> Not an integer, but converted to string (as property names of any
> object - only strings).
Therefore, too (all Numbers are floats), "equivalent". You want to check
your dictionary (and the Specification).
PointedEars
--
Anyone who slaps a 'this page is best viewed with Browser X' label on
a Web page appears to be yearning for the bad old days, before the Web,
when you had very little chance of reading a document written on another
computer, another word processor, or another network. -- Tim Berners-Lee
> Thomas 'PointedEars' Lahn wrote:
>> kangax wrote:
>>> Are you sure you haven't missed anything?
>>>
>>> "I would like to create own Object that would behave similar to Array
>>> Object, but would have defined some methods that are not in current
>>> ^^^^^^^^^^^^^^
>>> Array implementation. It need to not touch .prototype of an Array, so it
>>> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>> should work like this"
>>
>> So the thread has drifted a bit. Your approach touches ".prototype of an
>> Array", too. That you are using `__proto__' to refer to said object
>> instead, does not change that.
>
> Doesn't OP example make it clear what was meant by "touches"? If I
> understood it right, the snippet with __proto__ setting doesn't "touch"
> `Array.prototype`.
But the OP did not say "not use Array.prototype" to begin with; they said:
"not touch .prototype of an Array". And even if we assumed that ".prototype
of an Array" is meant as "Array.prototype", there is still ambiguity as to
what that is supposed to mean:
a) a specific property accessor
b) the object referred to by the value that the accessed property stores
It stands to reason that "not touch .prototype of an Array" or "not touch
Array.prototype" means (b), because the OP does not want to add (enumerable)
properties to that object (see for-in). And your suggestion of using
`[].__proto__' instead of `Array.prototype' in the source code does not help
with that because `[].__proto__ === Array.prototype' where `__proto__' is
supported. In fact, replacing the prototype object like you did decreases
runtime efficiency; maybe negligibly, but IMHO needlessly.
Of course he did. You just seem to have missed it again. Look at the
second comment of OP's example.
var a = [2,4,6];
a.someAddedFunction(); // error - no Array .prototype extending
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Now look a bit further down:
var c = new SuperArray([2,4,6]);
[...]
c.someAddedFunction(); // calls function
^^^^^^^^^^^^^^
How more clear should it be?
> "not touch .prototype of an Array". And even if we assumed that ".prototype
> of an Array" is meant as "Array.prototype", there is still ambiguity as to
> what that is supposed to mean:
>
> a) a specific property accessor
> b) the object referred to by the value that the accessed property stores
>
> It stands to reason that "not touch .prototype of an Array" or "not touch
> Array.prototype" means (b), because the OP does not want to add (enumerable)
> properties to that object (see for-in). And your suggestion of using
> `[].__proto__' instead of `Array.prototype' in the source code does not help
> with that because `[].__proto__ === Array.prototype' where `__proto__' is
The fact that `[].__proto__` and `Array.prototype` reference same object
is irrelevant here. The idea is to make sure `[]`'s [[Prototype]]
references another object (i.e. inject that object into a scope chain of
`[]`).
Changing `Array.prototype` would, obviously, change what
`Array.prototype` references, not what `[]`'s [[Prototype]] references.
I still don't see your point here.
> supported. In fact, replacing the prototype object like you did decreases
> runtime efficiency; maybe negligibly, but IMHO needlessly.
You mean now that we have one more object in prototype chain? Sure it
does, but, as you said, this is very likely so negligible that there's
no need to worry about it.
--
kangax
> Because it iterates over object properties, not over array members.
That is not true. What are you mean with "array members"? If you mean
decimal unsigned 32 bit indexes, you are not right, because they are
properties of that object.
e.g.
var a = ['test'];
window.alert('0' in a);
These properties is like any other properties of `object' in
JavaScript. When you getting value, you getting from prototype chain.
See below:
Object.prototype['0'] = 'test';
var a = [];
window.alert(a[0]);
For array objects for-in is feature. Only reason for me to stop using
for-in loops for arrays, is code produced from another programmers,
and JS lib who touched Array.prototype or anybody else `object' upward
in prototype chain.
Regards.
> [...]
> The goal is not in the OP, just the requirement to avoid modifying
> Array.prototype. There is still no need to avoid for-in on these new
> objects, just the likelihood that the values will need to be filtered if
> it is used on them. Then again it may be entirely feasible to avoid
> for-in on these objects while leaving it available for ordinary Arrays.
>
Yes, that's true from this point.
But today there's one issue with the meaning (and I see that on many
forums and the problem of OP - is also in this case): "Augmenting
prototypes of built-in objects is bad idea and bad practice". If
novice has heard such statement from some professional (which
understood what he was saying), the novice then will repeat that every
time and will believe that it's conclusive truth but even without
understanding why augmenting can make some troubles and in which cases
it can be treated as "bad idea".
But instead and vice versa - it's very good idea, as we have dynamic
and mutable objects in whose _ideology_ it's possible to augment any
object at any run-time with new plugged-in functionality as it would
be own functionality.
So, if somebody says that it's a bad idea and bad practice, he better
should recommend to use some static language.
The only (the only) reason is combining 3rd-party codes. In this case
we have two decisions:
(a) make good documentation of what we have augmented or
(b) to use own namespace and produce procedure-style such as
Ext.util.Format.capitalize(string) - that long crap instead of OOP-
style such as string.capitalize()
The issue with for-in loops (if we've decided to augment
Array.prototype) should not be afraid if we're talking about own
project but not combination of 3rd-party codes.
> [...]
> Yes, we have never known whether the use of for-in has any relevance for
> this object at all. I just mentioned because its use is impacted by any
> viable strategy adopted and it makes sense to be aware of that up-front.
> [...]
Yes, that's also of cause true.
But for-in loops is also not so useful (it's slower) as for-length
loops as they analyze prototype chain (for all that [push], [pop] and
so on properties) and make the check on any iteration such as [if (!
property.isEnumerable()) continue;].
And in here the only (the only) reason to use for-in for array - is
very sparse array. And for that aim, repeat, better to use Object. For
arrays is useful also functional-like style iterations.
But also issue can be with extension for-each-in loops (e.g. in array
comprehensions) where we can't check if object has such own property
and to filter other:
Array.prototype.x = 10;
var mapped = [k for each (k in [1, 2, 3, 4]) if (k % 2 == 0)]; // 2,
4, 10
So such extensions also should be, unfortunately, avoided.
/ds
>
> But for-in loops is also not so useful (it's slower) as for-length
> loops as they analyze prototype chain (for all that [push], [pop] and
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> so on properties) and make the check on any iteration such as [if (!
> property.isEnumerable()) continue;].
>
A little correction. Sure, prototype chain analysis can take place for
array and with [for-length] loops (but regardless for-length loop
itself - just via [[Get]]-method):
Array.prototype[0] = 10;
var a = [];
a[1] = 20;
for (var k = 0, length = a.length; k < length; k++) {
alert(a[k]); // 10, 20
}
But that's possible only again for sparse arrays, in normal case
(ordered indexes, 0-based started) this situation cannot be.
> Thomas 'PointedEars' Lahn wrote:
>> kangax wrote:
>>> Thomas 'PointedEars' Lahn wrote:
>>>> kangax wrote:
>>>>> Are you sure you haven't missed anything?
>>>>>
>>>>> "I would like to create own Object that would behave similar to Array
>>>>> Object, but would have defined some methods that are not in current
>>>>> ^^^^^^^^^^^^^^
>>>>> Array implementation. It need to not touch .prototype of an Array, so
>>>>> it ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>>>> should work like this"
>>>> So the thread has drifted a bit. Your approach touches ".prototype of
>>>> an
>>>> Array", too. That you are using `__proto__' to refer to said object
>>>> instead, does not change that.
>>> Doesn't OP example make it clear what was meant by "touches"? If I
>>> understood it right, the snippet with __proto__ setting doesn't "touch"
>>> `Array.prototype`.
>>
>> But the OP did not say "not use Array.prototype" to begin with; they
>> said:
>
> Of course he did.
Not in what you quoted.
> You just seem to have missed it again.
Or maybe I understood the OP differently?
> Look at the second comment of OP's example.
You did not quote that; Richard did, and it is hardly relevant.
> var a = [2,4,6];
> a.someAddedFunction(); // error - no Array .prototype extending
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
That is still not "Array.prototype". Look closer.
> Now look a bit further down:
>
> var c = new SuperArray([2,4,6]);
> [...]
> c.someAddedFunction(); // calls function
> ^^^^^^^^^^^^^^
>
> How more clear should it be?
"Array.prototype", but that would still be ambiguous (AISB).
>> "not touch .prototype of an Array". And even if we assumed that
>> ".prototype of an Array" is meant as "Array.prototype", there is still
>> ambiguity as to what that is supposed to mean:
>>
>> a) a specific property accessor
>> b) the object referred to by the value that the accessed property stores
>>
>> It stands to reason that "not touch .prototype of an Array" or "not touch
>> Array.prototype" means (b), because the OP does not want to add
>> (enumerable)
>> properties to that object (see for-in). And your suggestion of using
>> `[].__proto__' instead of `Array.prototype' in the source code does not
>> help with that because `[].__proto__ === Array.prototype' where
>> `__proto__' is
>
> The fact that `[].__proto__` and `Array.prototype` reference same object
> is irrelevant here.
It is not.
> The idea is to make sure `[]`'s [[Prototype]]
> references another object (i.e. inject that object into a scope chain of
> `[]`).
And thereby you overwrite the ".prototype of the Array" despite the OPs
requirement that it not be "touched".
> Changing `Array.prototype` would, obviously, change what
> `Array.prototype` references, not what `[]`'s [[Prototype]] references.
This is the same in green. [psf 4.5]
| 15.4.2.2 new Array(len)
|
| The [[Prototype]] property of the newly constructed object is set to the
| original Array prototype object, the one that is the initial value of
| Array.prototype (section 15.4.3.1). [...]
| 11.1.4 Array Initialiser
|
| [...]
| The production ArrayLiteral : [ Elision_opt ] is evaluated as follows:
|
| 1. Create a new array as if by the expression new Array().
|
| [...]
| The production ArrayLiteral : [ ElementList ] is evaluated as follows:
|
| 1. Evaluate ElementList.
| 2. Return Result(1).
|
| The production ArrayLiteral : [ ElementList , Elision_opt ] is evaluated
| as follows:
|
| 1. Evaluate ElementList.
| [...]
|
| The production ElementList : Elision_opt AssignmentExpression is evaluated
| as follows:
|
| 1. Create a new array as if by the expression new Array().
| [...]
> I still don't see your point here.
Read again. The OP very likely wants to avoid having an enumerable property
on the prototype object. Very likely they could not care less how the
prototype object is _not_ accessed.
>> supported. In fact, replacing the prototype object like you did
>> decreases runtime efficiency; maybe negligibly, but IMHO needlessly.
>
> You mean now that we have one more object in prototype chain? Sure it
> does, but, as you said, this is very likely so negligible that there's
> no need to worry about it.
One does if it does not satisfy the requirement of not modifying the
prototype to begin with. The was a purpose in that requirement that
you have ignored.
>[...]
>> error - no Array .prototype extending
> > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
> That is still not "Array.prototype". Look closer.
>
I hope you don't mean "there's a space before dot" in
"Array .prototype" vs. "Array.prototype"? :D If it's - i suggest you
to decrees you pathos ;)
> [...]
> > How more clear should it be?
>
> "Array.prototype"
>
ah, come on :) it's sort of joke or I missed something? ;)
> [...]
> > The idea is to make sure `[]`'s [[Prototype]]
> > references another object (i.e. inject that object into a scope chain of
> > `[]`).
>
> And thereby you overwrite the ".prototype of the Array" despite the OPs
> requirement that it not be "touched".
>
Excuse me, do you really don't understand what OP have asked? Or it's
again kind of privileged humor that I can't get in? ;)
> > Changing `Array.prototype` would, obviously, change what
> > `Array.prototype` references, not what `[]`'s [[Prototype]] references.
>
> This is the same in green. [psf 4.5]
>
Changing [].[[Prototype]] as modifying - sure will affect on original
Array.prototype, but here the talk about changing in meaning of full
changing, where object on which Array.prototype points will not be
touched.
>
> Read again. The OP very likely wants to avoid having an enumerable property
> on the prototype object. Very likely they could not care less how the
> prototype object is _not_ accessed.
>
OP just wants do not touch object on with points Array.prototype
('cause someone whom he believes as authority recommended that) - as
he afraid of for-in loops for ordinary arrays. He just want to create
own extension and kangax and Richard give such examples, though, OP
still should "afraid" of for-in loops for that extended object, but
not for the ordinary arrays => goal is reached. What exactly you don't
understand?
Ok.
>
>> Look at the second comment of OP's example.
>
> You did not quote that; Richard did, and it is hardly relevant.
Should I quote specific lines every time? Are you not able to understand
the issue as a whole? Everyone seemed to have understood OP identically
(more or less), except you.
Think outside the box ;)
>
>> var a = [2,4,6];
>> a.someAddedFunction(); // error - no Array .prototype extending
>> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
> That is still not "Array.prototype". Look closer.
You're joking, right? :)
>
>> Now look a bit further down:
>>
>> var c = new SuperArray([2,4,6]);
>> [...]
>> c.someAddedFunction(); // calls function
>> ^^^^^^^^^^^^^^
>>
>> How more clear should it be?
>
> "Array.prototype", but that would still be ambiguous (AISB).
Oh, come on.
[...]
>> The idea is to make sure `[]`'s [[Prototype]]
>> references another object (i.e. inject that object into a scope chain of
>> `[]`).
>
> And thereby you overwrite the ".prototype of the Array" despite the OPs
> requirement that it not be "touched".
Overwrite it? Where?
Let's look at a snippet again:
var augment = (function(){
var mixin = {
last: function() {
return this[this.length-1];
},
__proto__: Array.prototype
};
return function(object) {
object.__proto__ = mixin;
return object;
};
})();
var arr = augment([1,2,3]);
Please show me at which point is `Array.prototype` "overwritten" (or, to
be specific � at which point does `Array.prototype` reference object
different than the one it originally references and/or at which point do
the properties of that object get modified)?
Of course. In fact, that enumerable property is never added to
`Array.prototype`, just as OP asked.
What is the problem here?
[...]
--
kangax
I bet he's trying hard not to say that it's the instance's
original .__proto__ what should go inside __proto__ in the 'mixin',
instead of assuming that it was === Array.prototype.
--
Jorge.
They did not. In any case:
The fact that an opinion has been widely held is no evidence whatever that
it is not utterly absurd; indeed in view of the silliness of the majority
of mankind, a widespread belief is more likely to be foolish than
sensible.
-- Bertrand Russell (1872-1970 CE)
> Think outside the box ;)
The box that you do not want to see is that "not touch the .prototype of an
Array" was very likely a figure of speech to say "not augment the prototype
object of an Array instance."
>>> var a = [2,4,6];
>>> a.someAddedFunction(); // error - no Array .prototype extending
>>> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>
>> That is still not "Array.prototype". Look closer.
>
> You're joking, right? :)
I do not.
>>> Now look a bit further down:
>>>
>>> var c = new SuperArray([2,4,6]);
>>> [...]
>>> c.someAddedFunction(); // calls function
>>> ^^^^^^^^^^^^^^
>>>
>>> How more clear should it be?
>>
>> "Array.prototype", but that would still be ambiguous (AISB).
>
> Oh, come on.
Is that supposed to be an argument?
>>> The idea is to make sure `[]`'s [[Prototype]]
>>> references another object (i.e. inject that object into a scope chain of
>>> `[]`).
>>
>> And thereby you overwrite the ".prototype of the Array" despite the OPs
>> requirement that it not be "touched".
>
> Overwrite it? Where?
>
> Let's look at a snippet again:
>
> var augment = (function(){
> var mixin = {
> last: function() {
> return this[this.length-1];
> },
> __proto__: Array.prototype
> };
> return function(object) {
> object.__proto__ = mixin;
> return object;
> };
> })();
>
> var arr = augment([1,2,3]);
That is _not_ the code in question. The code in question has been commented
on first in <news:6582835.2...@PointedEars.de>, and posted by you in
<news:uq6dnerJAYtGunrX...@giganews.com>.
In any case, both approaches fail to address the requirement of "not
touch[ing] the .prototype of an Array". The resulting Array instance will
inherit enumerable properties that show up in for-in iteration.
PointedEars
--
realism: HTML 4.01 Strict
evangelism: XHTML 1.0 Strict
madness: XHTML 1.1 as application/xhtml+xml
-- Bjoern Hoehrmann
Man, sorry, but you're just collection of "authority" cites ;) Do you
have your own opinion? I mean beside your shor "No.", "The did not.",
"No they are not" and so on - pathos phrases of those who belive
himself higher that other. Decrease your pathos, I repeat, it really
will be better ;)
> [...]
> > You're joking, right? :)
>
> I do not.
>
One more time :) "You do not". "No.", "They do not.", "Everybody's
lie.", "No." ;)
> >>> Now look a bit further down:
>
> >>> var c = new SuperArray([2,4,6]);
> >>> [...]
> >>> c.someAddedFunction(); // calls function
> >>> ^^^^^^^^^^^^^^
>
> >>> How more clear should it be?
>
> >> "Array.prototype", but that would still be ambiguous (AISB).
>
> > Oh, come on.
>
> Is that supposed to be an argument?
>
What argument do you expect else in case of your troll-like style
speaking (I mean concrete this one thread)?
> [...]
> In any case, both approaches fail to address the requirement of "not
> touch[ing] the .prototype of an Array". The resulting Array instance will
> inherit enumerable properties that show up in for-in iteration.
>
You still continue to sing your song, just because you can't say
(yeah, I understand - it's hard, when you believe yourself higher than
other ;)) - "sorry, guys, I did't understand it correctly", you still
continue talking about stupid "the .prototype of an Array" ===
"[[Prototype]] of []" without listening kangax.
k, one more time: You didn't understand it correctly. OP has meant: "I
don't want to touch the object on which points Array.prototype as I
don't wanna break down [for-in] loops for ordinary arrays. But I don't
care what will be in [for-in] loops with own extended object". Is it
so hard to understand? ;)
> Thomas 'PointedEars' Lahn wrote:
>> kangax wrote:
>> > Should I quote specific lines every time? Are you not able to
>> > understand the issue as a whole? Everyone seemed to have understood OP
>> > identically (more or less), except you.
>>
>> They did not. In any case:
>>
>> The fact that an opinion has been widely held is no evidence whatever
>> that it is not utterly absurd; indeed in view of the silliness of the
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> majority of mankind, a widespread belief is more likely to be foolish
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> than sensible.
^^^^^^^^^^^^^^
>> -- Bertrand Russell (1872-1970 CE)
>
> [...]
>> [...]
>> In any case, both approaches fail to address the requirement of "not
>> touch[ing] the .prototype of an Array". The resulting Array instance
>> will inherit enumerable properties that show up in for-in iteration.
>
> You still continue to sing your song, just because you can't say
> (yeah, I understand - it's hard, when you believe yourself higher than
> other ;)) - "sorry, guys, I did't understand it correctly", you still
> continue talking about stupid "the .prototype of an Array" ===
> "[[Prototype]] of []" [...]
q.e.d.
:D don't be worry, you already lost ;)
Again advise to you (you should sure ignore it ;)) - try to discuss
with more scientific approach and without thinking that you're higher
than other (if you want the objective meaning - you're now just a bit
deeper in ES than casual programmer, so don't lie to yourself when
talking with other from the top ;)).
And yep - the talk is over with you.
wilq32
??... as you wish of course...
Out of curiosity, what is exactly dysfunctional and on what platform
in the posted solution?
http://groups.google.com/group/comp.lang.javascript/msg/13d8201987b9d24e