HighDots Forums  

Creating an Object that extends Array functionality

Javascript JavaScript language (comp.lang.javascript)


Discuss Creating an Object that extends Array functionality in the Javascript forum.



Reply
 
Thread Tools Display Modes
  #31  
Old   
Richard Cornford
 
Posts: n/a

Default Re: Creating an Object that extends Array functionality - 10-27-2009 , 07:53 PM






Dmitry A. Soshnikov wrote:
Quote:
On Oct 27, 4:00 pm, Richard Cornford wrote:
[...]
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?
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.

Quote:
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.

Reply With Quote
  #32  
Old   
kangax
 
Posts: n/a

Default Re: Creating an Object that extends Array functionality - 10-27-2009 , 08:48 PM






Dmitry A. Soshnikov wrote:
Quote:
On Oct 28, 1:24 am, kangax <kan... (AT) gmail (DOT) com> wrote:
Thomas 'PointedEars' Lahn wrote:
kangax wrote:
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?
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"


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?
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.

Quote:
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.

[...]

Reply With Quote
  #33  
Old   
kangax
 
Posts: n/a

Default Re: Creating an Object that extends Array functionality - 10-27-2009 , 09:09 PM



Thomas 'PointedEars' Lahn wrote:
Quote:
kangax wrote:

Thomas 'PointedEars' Lahn wrote:
kangax wrote:
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?
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`.

Quote:
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

Reply With Quote
  #34  
Old   
Jorge
 
Posts: n/a

Default Re: Creating an Object that extends Array functionality - 10-28-2009 , 04:43 AM



On Oct 27, 11:03*pm, Thomas 'PointedEars' Lahn <PointedE... (AT) web (DOT) de>
wrote:
Quote:
kangax wrote:
Thomas 'PointedEars' Lahn wrote:

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 usingthe 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.)
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.

Reply With Quote
  #35  
Old   
Dmitry A. Soshnikov
 
Posts: n/a

Default Re: Creating an Object that extends Array functionality - 10-28-2009 , 04:46 AM



On Oct 28, 2:12*am, Thomas 'PointedEars' Lahn <PointedE... (AT) web (DOT) de>
wrote:

Quote:
[...]
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).

Reply With Quote
  #36  
Old   
Thomas 'PointedEars' Lahn
 
Posts: n/a

Default Re: Creating an Object that extends Array functionality - 10-28-2009 , 07:16 AM



Dmitry A. Soshnikov wrote:

Quote:
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

Reply With Quote
  #37  
Old   
Thomas 'PointedEars' Lahn
 
Posts: n/a

Default Re: Creating an Object that extends Array functionality - 10-28-2009 , 07:33 AM



kangax wrote:

Quote:
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.


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$8300dec7 (AT) news (DOT) demon.co.uk>

Reply With Quote
  #38  
Old   
kangax
 
Posts: n/a

Default Re: Creating an Object that extends Array functionality - 10-28-2009 , 09:10 AM



Thomas 'PointedEars' Lahn wrote:
Quote:
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. 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?

Quote:
"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.

Quote:
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

Reply With Quote
  #39  
Old   
Asen Bozhilov
 
Posts: n/a

Default Re: Creating an Object that extends Array functionality - 10-28-2009 , 02:09 PM



On 28 οΛΤ, 01:07, VK <schools_r... (AT) yahoo (DOT) com> wrote:

Quote:
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.

Reply With Quote
  #40  
Old   
Dmitry A. Soshnikov
 
Posts: n/a

Default Re: Creating an Object that extends Array functionality - 10-28-2009 , 02:10 PM



On Oct 28, 2:53*am, "Richard Cornford" <Rich... (AT) litotes (DOT) demon.co.uk>
wrote:

Quote:
[...]
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.


Quote:
[...]
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

Reply With Quote
Reply




Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Powered by vBulletin Version 3.5.4
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.