Object Hash vs. object Array preference

Discussion in 'Javascript' started by VK, Nov 11, 2005.

  1. VK

    VK Guest

    Hello,
    In my object I have getDirectory() method which returns 2-dimentional
    array
    (or an imitation of 2-dimentional array using two JavaScript objects
    with auto-handled length property - please let's us do not go into an
    "each dot over i" clarification discussion now - however you want to
    call - you call it ;-)

    array[0] contains records of all files in the current dir.
    array[1] contains records of all subs in the current dir

    Each records is in its turn is an array of 6 elements: file/folder
    name, size, type, attributes, lastModified date, lastModified time.

    Tking into account that someone will need to build a dialog interface
    over this data IMHO array structure is the most suitable ('cause of
    sorting issue).

    Or a custom object on each directory entry still would be more
    flexible? What would you personally prefer to get out of the functiuon
    for easier programming?
     
    VK, Nov 11, 2005
    #1
    1. Advertising

  2. VK wrote:

    > In my object I have getDirectory() method which returns 2-dimentional
    > array
    > (or an imitation of 2-dimentional array using two JavaScript objects
    > with auto-handled length property - please let's us do not go into an
    > "each dot over i" clarification discussion now - however you want to
    > call - you call it ;-)


    I can accept the term "2-dimensional array" for brevity, provided that
    each element has the same number of subelements.

    > array[0] contains records of all files in the current dir.
    > array[1] contains records of all subs in the current dir
    >
    > Each records is in its turn is an array of 6 elements: file/folder
    > name, size, type, attributes, lastModified date, lastModified time.
    >
    > Tking into account that someone will need to build a dialog interface
    > over this data IMHO array structure is the most suitable ('cause of
    > sorting issue).


    I don't understand this argument. What has sorting to do with it?

    > Or a custom object on each directory entry still would be more
    > flexible? What would you personally prefer to get out of the functiuon
    > for easier programming?


    I'd prefer an Object-based object here since it is more difficult to
    remember the index of the array element than the meaningful identifier
    of the property. If needed later, an Array object can be extended to
    a collection so that both access methods can be used.


    PointedEars
     
    Thomas 'PointedEars' Lahn, Nov 11, 2005
    #2
    1. Advertising

  3. VK

    VK Guest

    > > VK wrote:
    > > Tking into account that someone will need to build a dialog interface
    > > over this data IMHO array structure is the most suitable ('cause of
    > > sorting issue).

    ..
    > Thomas 'PointedEars' Lahn wrote:
    > I don't understand this argument. What has sorting to do with it?


    I meant to say that you cannot sort hash keys (object properties,
    collection items - the Legion is its name) but you can sort arrays.
    Need to admit though that in case like
    record[e1, e2, e3, e4, e5] > sort all records by e4
    I'm pretty cloudy about the best accepted mechanics and therefore I'm
    not sure what to serve better: an Object or an Array. I used to handle
    such issues on server-side through mySQL where the boring part is done
    automatically on the background.
    ..
    > Thomas 'PointedEars' Lahn wrote:
    > I'd prefer an Object-based object here since it is more difficult to
    > remember the index of the array element than the meaningful identifier
    > of the property. If needed later, an Array object can be extended to
    > a collection so that both access methods can be used.

    That's not so much a question of usability but a question of
    productivity.
    Firstly the served object will be used for LOOKUP operations
    exclusively (you cannot delete files/properties or add new ones here).
    Secondly it will be used for LOOKUP operations very intensively. On a
    big directory (over 100 files) display/sorting/selection will take
    thousands of lookups so even 1ms difference will add up easily. I guess
    it brings up the old question: is there any productivity difference
    between Object and Array for lookup operations?
     
    VK, Nov 12, 2005
    #3
  4. "VK" <> writes:

    > I meant to say that you cannot sort hash keys (object properties,
    > collection items - the Legion is its name) but you can sort arrays.


    Sorting implies ordering, which again implies indexability by counting
    numbers, so yes, array elements can be sorted, rearranging their
    property names. There is no ordering of general properties of objects,
    so it's not even possible to define a notion of sorting on them.

    > Need to admit though that in case like
    > record[e1, e2, e3, e4, e5] > sort all records by e4


    Not understood. If each record is a five element array, and you want
    to sort it by its fourth element, then I'd do something like:
    ---
    // generic comparison function
    function cmp(a,b) {
    return (b<a)-(a<b);
    }

    // creates function that compares property prop of arguments.
    function cmpProperty(prop) {
    return function (a,b) {
    return cmp(a[prop],b[prop]);
    };
    }

    // sort records by fourth element.
    records.sort(cmpProperty(3));
    ---

    > I'm pretty cloudy about the best accepted mechanics and therefore I'm
    > not sure what to serve better: an Object or an Array.


    Doesn't matter. You compare a property of the object, whether it's
    called "3" or "foo" is irrelevant. So if you use the record anywhere
    else, use meaningful names.


    > I guess it brings up the old question: is there any productivity
    > difference between Object and Array for lookup operations?


    That depends on the implementation of Javascript it is running on.

    A quick test:
    ---
    function timeLookup(obj,prop, N) {
    var t0 = new Date();
    var x;
    while(N--) {
    x = obj[prop];
    }
    var t1 = new Date();
    return t1-t0;
    }

    var N = 1000000;
    var a = ["lal","lal","lala","lalala","lalalaalla"];
    var t0 = timeLookup(a,"3", N);
    var t1 = timeLookup(a,3, N);

    var o = {"diller":"lal","daller":"lal","y":"lala","3":"lalala",
    "anguish":"lalalaalla"};
    var t2 = timeLookup(o, "3", N);

    var o2 = {"diller":"lal","daller":"lal","y":"lala","x":"lalala",
    "anguish":"lalalaalla"};
    var t3 = timeLookup(o2, "x", N);

    var o3 = {"diller":"lal","daller":"lal","y":"lala",
    "dallerdallerdaller":"lalala","anguish":"lalalaalla"};
    var t4 = timeLookup(o3, "dallerdallerdaller", N);

    [t0,t1,t2,t3,t4]
    ---
    gives the following results (times in ms):
    array["3"] array[3] object["3"] object["x"] object["daller...."]
    Opera 922 766 906 797 843
    IE 6 906 891 891 937 1093
    FF 746 406 750 625 906

    So, of these, only Firefox seems to have a significantly more
    efficient array lookup than property lookup, but longer property
    names makes for longer lookup times.

    It should probably also be tested on objects/arrays with lots
    of properties, not just five.

    Both Opera and Firefox seems to take extra time when the property is a
    string containing a number literal, even when used on an object, not
    an array. One can wonder why :)

    /L
    --
    Lasse Reichstein Nielsen -
    DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
    'Faith without judgement merely degrades the spirit divine.'
     
    Lasse Reichstein Nielsen, Nov 12, 2005
    #4
  5. VK

    VK Guest


    > Lasse Reichstein Nielsen wrote:
    > If each record is a five element array, and you want
    > to sort it by its fourth element, then I'd do something like:
    > ---
    > // generic comparison function
    > function cmp(a,b) {
    > return (b<a)-(a<b);
    > }
    >
    > // creates function that compares property prop of arguments.
    > function cmpProperty(prop) {
    > return function (a,b) {
    > return cmp(a[prop],b[prop]);
    > };
    > }
    >
    > // sort records by fourth element.
    > records.sort(cmpProperty(3));


    Rather elegant but requires Object<>Array back and forth casting which
    will swallow any productivity difference advantages between of them ?

    > A quick test:
    > ---
    > function timeLookup(obj,prop, N) {
    > var t0 = new Date();
    > var x;
    > while(N--) {
    > x = obj[prop];
    > }
    > var t1 = new Date();
    > return t1-t0;
    > }
    >
    > var N = 1000000;
    > var a = ["lal","lal","lala","lalala","lalalaalla"];
    > var t0 = timeLookup(a,"3", N);
    > var t1 = timeLookup(a,3, N);
    >
    > var o = {"diller":"lal","daller":"lal","y":"lala","3":"lalala",
    > "anguish":"lalalaalla"};
    > var t2 = timeLookup(o, "3", N);
    >
    > var o2 = {"diller":"lal","daller":"lal","y":"lala","x":"lalala",
    > "anguish":"lalalaalla"};
    > var t3 = timeLookup(o2, "x", N);
    >
    > var o3 = {"diller":"lal","daller":"lal","y":"lala",
    > "dallerdallerdaller":"lalala","anguish":"lalalaalla"};
    > var t4 = timeLookup(o3, "dallerdallerdaller", N);
    >
    > [t0,t1,t2,t3,t4]
    > ---
    > gives the following results (times in ms):
    > array["3"] array[3] object["3"] object["x"] object["daller...."]
    > Opera 922 766 906 797 843
    > IE 6 906 891 891 937 1093
    > FF 746 406 750 625 906
    >
    > So, of these, only Firefox seems to have a significantly more
    > efficient array lookup than property lookup, but longer property
    > names makes for longer lookup times.


    Wow: double speed gain on Array with FF. These are 1-10 seconds speed
    gain for application I guess - if you manage to stay within Array only.
    IE seems rather indifferent but still just a bit quicklier. So I'd
    explore Array-only solutions first if any is possible.

    > It should probably also be tested on objects/arrays with lots
    > of properties, not just five.


    That's not my case, but I'd welcome any volunteer ;-)

    > Both Opera and Firefox seems to take extra time when the property is a
    > string containing a number literal, even when used on an object, not
    > an array. One can wonder why :)


    Was that a rhetorical question? :)
    Naturally arr["3"] takes longer because the system is trying to find
    first CDATA-named property "1", fails on that and only then it gets
    array element with index 3.
     
    VK, Nov 12, 2005
    #5
  6. VK wrote:

    > Lasse Reichstein Nielsen wrote:
    >> Both Opera and Firefox seems to take extra time when the property is a
    >> string containing a number literal, even when used on an object, not
    >> an array. One can wonder why :)

    >
    > Was that a rhetorical question? :)
    > Naturally arr["3"] takes longer because the system is trying to find
    > first CDATA-named property "1", fails on that and only then it gets
    > array element with index 3.


    CDATA is a data type specified in SGML/XML and used in DTDs for markup
    languages. We are talking about a programming language specification
    and its implementation, particularly ECMAScript 3 [1], subsection 11.2.1.

    Will you learn how to quote?


    PointedEars
    ___________
    [1] <http://www.mozilla.org/js/language/E262-3.pdf>
     
    Thomas 'PointedEars' Lahn, Nov 12, 2005
    #6
  7. VK

    VK Guest


    > Thomas 'PointedEars' Lahn wrote:
    > CDATA is a data type specified in SGML/XML and used in DTDs for markup
    > languages. We are talking about a programming language specification
    > and its implementation, particularly ECMAScript 3 [1], subsection 11.2.1.


    ?

    JavaScript/JScript Object accepts CDATA literals as property name.

    Array index is unsigned 32 bit value which allows you to hold
    4294967295 array elements per array-that's one less than 32 bits can
    hold: the remaining one is used for the length value.

    So in case:
    someObject["3"] = "foo";
    interpreter checks first if the key can be converted into an integer in
    the range 0,..., 4294967295
    If it can then someObject is treated as array (if contextually
    possible) and its element with index 3 gets value "foo".

    If the key cannot be converted into integer or if such integer goes
    outside of the 0,..., 4294967295 range then the value is used as new
    property name:
    someObject["-1.5"] = "foo"; // creates key "-1.5" with value "foo"
    someObject["4294967296"] = "foo"; // creates key "4294967296" with
    value "foo"

    By explicetly serving a valid index value to a pre-declared array:
    someArray[3] = "foo";
    you free the interpreter from the unnecessary checks/transformations
    and you get a noticeable productivity gain.

    In this concern I don't care too much (actually I don't care at all) if
    ECMA specs are saying something other, because this is how it does
    really work on any browser I know of.

    > Will you learn how to quote?


    Well, sorry but I used to quote in the way one can see who am I
    answering to (if there are several responses) and what am I answering
    to:
    Poster Name / Nickname wrote:
    Quote
    My answer
    ....
    and I don't see any reason to change this habit unless some really
    serious *logical* reasons will be provided (to fix it right away:
    written rules are not one of them ;-)
     
    VK, Nov 12, 2005
    #7
  8. "VK" <> writes:

    > Rather elegant but requires Object<>Array back and forth casting which
    > will swallow any productivity difference advantages between of them ?


    There is no casting anywhere. In Javascript, arrays *are* objects, and
    their numbered properties are just that: object properties. The only
    "magic" in arrays are in the internal [[put]] method, which keeps
    the "length" property in sync with the numbered properties. A literal
    implementation of the ECMAScript specification of objects would use
    the same [[get]] method for arrays and non-array objects.

    > Wow: double speed gain on Array with FF. These are 1-10 seconds speed
    > gain for application I guess - if you manage to stay within Array only.


    Only if the application does nothing but array accesses and takes 2-20
    seconds to run.

    > IE seems rather indifferent but still just a bit quicklier.


    That small a difference could easily be within the measuring
    uncertainty.

    >> Both Opera and Firefox seems to take extra time when the property is a
    >> string containing a number literal, even when used on an object, not
    >> an array. One can wonder why :)

    >
    > Was that a rhetorical question? :)
    > Naturally arr["3"] takes longer because the system is trying to find
    > first CDATA-named property "1", fails on that and only then it gets
    > array element with index 3.


    That makes no sense. "CDATA" is an HTML type, not something that
    exists in Javascript. If you just mean "string", then it's still
    an interesting result, since the ECMAScript standard describes all
    properties as strings, even array properties. The curious part was
    that even on a non-array object, useing "3" as property name takes
    longer than using "x", even though there is no reason to treat
    numerals different from other property names.

    /L
    --
    Lasse Reichstein Nielsen -
    DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
    'Faith without judgement merely degrades the spirit divine.'
     
    Lasse Reichstein Nielsen, Nov 12, 2005
    #8
  9. VK wrote:

    [Quotation corrected]

    > Thomas 'PointedEars' Lahn wrote:
    >> CDATA is a data type specified in SGML/XML and used in DTDs for markup
    >> languages. We are talking about a programming language specification
    >> and its implementation, particularly ECMAScript 3 [1], subsection 11.2.1.

    >
    > ?
    >
    > JavaScript/JScript Object accepts CDATA literals as property name.


    Sorry, but this *is* utter nonsense indeed. You obviously have no idea
    what CDATA is. Hint: there is not one reference to it in the ECMAScript
    Specification, or any _JS language_ reference for that matter.

    We are talking about built-in language objects here, not host DOM
    objects where a reference to the CDATA type might be appropriate.

    > Array index is unsigned 32 bit value


    Yes.

    > which allows you to hold 4294967295 array elements per array- that's one
    > less than 32 bits can hold: the remaining one is used for the length
    > value.


    With this description, I am not sure we understand each other as it was
    meant.

    32 bits allow you to store 4294967296 different unsigned states. That is
    4294967295 non-zero states plus the zero state. Which is why you could
    _theoretically_ hold 4294967296 elements in one Array, where the minimum
    element index is 0 and the maximum one is 4294967295. However, since
    there has to be a _separate_ `length' property that also can only hold
    an unsigned 32-bit integer (range from 0 to 2^32-1 = 4294967295) at the
    maximum as well, only 4294967295 elements are allowed and thus only
    4294967294 is allowed for maximum index.

    > By explicetly serving a valid index value to a pre-declared array:
    > someArray[3] = "foo";
    > you free the interpreter from the unnecessary checks/transformations


    No.

    ,-<http://www.mozilla.org/js/language/E262-3.pdf>
    |
    | [...]
    | 11.2 Left-Hand-Side Expressions
    |
    | Syntax
    |
    | MemberExpression :
    | PrimaryExpression
    | FunctionExpression
    | MemberExpression [ Expression ]
    | MemberExpression . Identifier
    | new MemberExpression Arguments
    |
    | [...]
    | The production MemberExpression : MemberExpression [ Expression ] is
    | evaluated as follows:
    |
    | 1. Evaluate MemberExpression.
    | 2. Call GetValue(Result(1)).
    | 3. Evaluate Expression.
    | 4. Call GetValue(Result(3)).
    | 5. Call ToObject(Result(2)).
    | 6. Call ToString(Result(4)).
    ^^^^^^^^^^^^^^^^^^^^^^^^
    | 7. Return a value of type Reference whose base object is Result(5) and
    | whose property name is Result(6).

    As you can see, if the implementation is standards compliant, all parameters
    of the bracket property accessor are converted to String first. And *then*
    follows

    | 15.4 Array Objects
    |
    | Array objects give special treatment to a certain class of property names.
    | A property name P (in the form of a string value) is an array index if and
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    | only if ToString(ToUint32(P)) is equal to P and ToUint32(P) is not equal
    | to 2^32?1.

    So in terms of "saving the 'interpreter' work" it would be even more
    efficient to always quote all parameters for the bracket property
    accessor, thus saving it from type conversion in the abstract internal
    ToString operator which is defined as follows:

    | 9.8 ToString
    |
    | The operator ToString converts its argument to a value of type
    | String according to the following table:
    |
    | Input Type Result
    | ------------------------------------------------------------------
    | Undefined "undefined"
    | Null "null"
    | Boolean If the argument is true, then the result is "true".
    | If the argument is false, then the result is "false".
    | Number See note below.
    | String Return the input argument (no conversion)
    | Object Apply the following steps:
    | Call ToPrimitive(input argument, hint String).
    | Call ToString(Result(1)).
    | Return Result(2).
    |
    | 9.8.1 ToString Applied to the Number Type
    |
    | [too much to be quoted here, go read on that yourself]

    You have not bothered to read the section of the specification I have
    referred to and the other sections it is referring to. Again.

    > and you get a noticeable productivity gain.


    The reasons for this lie elsewhere, it is perhaps due to a not conforming
    implementation.

    >> Will you learn how to quote?

    >
    > Well, sorry but I used to quote in the way one can see who am I
    > answering to (if there are several responses) and what am I answering
    > to:
    > Poster Name / Nickname wrote:
    > Quote
    > My answer
    > ...
    > and I don't see any reason to change this habit unless some really
    > serious *logical* reasons will be provided (to fix it right away:
    > written rules are not one of them ;-)


    Your quotes are like this:

    | > > User 1 wrote:
    | > > [Text of User 1]
    | .
    | > User 2 wrote:
    | > [Text of User 2]
    |
    | Your text

    Expected (and, it appears to me, accepted) is:

    | User 2 wrote:
    | > User 1 wrote:
    | > > [Text of User 1]
    | >
    | > [Text of User 2]
    |
    | Your text

    Not only that the initial attribution line is to indicate who wrote what, to
    allow quotes to be trimmed easily, the quotation character sequence is to
    indicate the quotation level, to be able to assign quoted text to a person
    easily.


    HTH

    PointedEars
     
    Thomas 'PointedEars' Lahn, Nov 12, 2005
    #9
  10. Lasse Reichstein Nielsen wrote:

    > "VK" <> writes:
    >> Naturally arr["3"] takes longer because the system is trying to find
    >> first CDATA-named property "1", fails on that and only then it gets
    >> array element with index 3.

    >
    > That makes no sense. "CDATA" is an HTML type, not
    > something that exists in Javascript.


    Just to have my daily nitpick: it is an _SGML_ type :)


    SCNR
    PointedEars
     
    Thomas 'PointedEars' Lahn, Nov 12, 2005
    #10
  11. "VK" <> writes:

    > JavaScript/JScript Object accepts CDATA literals as property name.


    No, that's confuzing terms. CDATA is a type in HTML documents. In the
    DOM, the contents of CDATA sections and attributes are available as
    Javascript strings. Objects accept *strings* as property names.

    It might be a little pedantic, but its still correct :)

    > Array index is unsigned 32 bit value which allows you to hold
    > 4294967295 array elements per array-that's one less than 32 bits can
    > hold: the remaining one is used for the length value.


    Yes. (It's not that the last property is used to hold the length
    property, as this could be misunderstood to say, just that the length
    must be a 32 bit unsigned number and must be able to be one larger
    than the largest used array index).

    > So in case:
    > someObject["3"] = "foo";
    > interpreter checks first if the key can be converted into an integer in
    > the range 0,..., 4294967295


    It shouldn't (or needen't) do that according to the ECMAScript
    specification. The expressions
    someObject["3"]
    and
    someObject["03"]
    access different properties. If someObject is an array, only the first
    corresponds to an array element, so "can be converted into an integer"
    is imprecise. A more precise way of saying it would be:
    if the key is the canonical representation of an unsigned integer
    in the range 0 .. 2^32-2...

    > If it can then someObject is treated as array (if contextually
    > possible) and its element with index 3 gets value "foo".


    There is no "treating like an array". All properties are equal on
    objects, arrays or not. Non-array objects are not "treated like
    objects" if you use "3" as a property name, an array-objects
    are not "treated like" objects when you use "x" - they *are*
    objects.

    Only when assigning to properties on an array is there a difference,
    and only when assigning to a property name that is the canonical form
    of an array index or is "length".

    > If the key cannot be converted into integer or if such integer goes
    > outside of the 0,..., 4294967295 range then the value is used as new
    > property name:
    > someObject["-1.5"] = "foo"; // creates key "-1.5" with value "foo"
    > someObject["4294967296"] = "foo"; // creates key "4294967296" with
    > value "foo"


    And
    someObject["123"] = "foo" // creates key "123" with value "foo"
    // *and* if someObject is an array with
    // someObject["length"] <= 123, it updates
    // someObject["length"] to 124.

    > By explicetly serving a valid index value to a pre-declared array:
    > someArray[3] = "foo";
    > you free the interpreter from the unnecessary checks/transformations
    > and you get a noticeable productivity gain.


    That is a possible optimization an implementation can do. You can keep
    "array index" named properties as numbers and not convert the operand
    to a string before doing the lookup. It seems most browsers does something
    of this sort, even on non-arrays, which accounts for the larger overhead
    when using the string "3" as operand of the property access operation.

    > In this concern I don't care too much (actually I don't care at all) if
    > ECMA specs are saying something other, because this is how it does
    > really work on any browser I know of.


    Do you have documentation of that? Which browsers do you know of?

    /L
    --
    Lasse Reichstein Nielsen -
    DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
    'Faith without judgement merely degrades the spirit divine.'
     
    Lasse Reichstein Nielsen, Nov 12, 2005
    #11
  12. Lasse Reichstein Nielsen wrote:

    > "VK" <> writes:
    >> If it can then someObject is treated as array (if contextually
    >> possible) and its element with index 3 gets value "foo".

    >
    > There is no "treating like an array".


    Exactly.

    > All properties are equal on objects, arrays or not.


    No, see <>.

    > [...]
    > Only when assigning to properties on an array is there a difference,
    > and only when assigning to a property name that is the canonical form
    > of an array index or is "length".


    Certainly not.

    >> By explicetly serving a valid index value to a pre-declared array:
    >> someArray[3] = "foo";
    >> you free the interpreter from the unnecessary checks/transformations
    >> and you get a noticeable productivity gain.

    >
    > That is a possible optimization an implementation can do. You can keep
    > "array index" named properties as numbers and not convert the operand
    > to a string before doing the lookup.


    Where is this backed up by ECMAScript 3 as an allowed optimization for
    a compliant implementation?


    PointedEars
     
    Thomas 'PointedEars' Lahn, Nov 12, 2005
    #12
  13. VK

    VK Guest

    > Lasse Reichstein Nielsen wrote:
    > There is no casting anywhere. In Javascript, arrays *are* objects, and
    > their numbered properties are just that: object properties. The only
    > "magic" in arrays are in the internal [[put]] method, which keeps
    > the "length" property in sync with the numbered properties. A literal
    > implementation of the ECMAScript specification of objects would use
    > the same [[get]] method for arrays and non-array objects.


    Sorry but that's an urban legend greatly dispropaganded in the 3rd
    edition of my <http://www.geocities.com/schools_ring/ArrayAndHash.html>
    and it will be completely busted in the 4th one I'm hoping to finish
    before Christmas. To facilitate the cultural shock some people may
    experience :) here a piece of tast cases directly related to the
    current OP. You are welcome to put each position into your own
    benchmark test.
    All comments are inside.

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <html>
    <head>
    <title>Test Template</title>
    <meta http-equiv="Content-Type" content="text/html;
    charset=iso-8859-1">

    <script type="text/javascript">

    var obj = {};
    var arr = [];

    function init() {
    }

    function test() {

    /**
    * Each block below should be uncommented
    * separately before testing and commented
    * back before moving to the next block
    */


    /**
    * Both Hashtable (used for Object) and Array
    * accept non-ECMA naming compliant literals as property name:
    */
    //obj["^^^CDATA^^^"] = "foo";
    //arr["^^^CDATA^^^"] = "foo";
    //alert(obj["^^^CDATA^^^"]); // "foo"
    //alert(arr["^^^CDATA^^^"]); // "foo"


    /**
    * Array neither counts its properties
    * as array elements nor it knows anything
    * about them:
    */
    //alert(arr.length); // 0

    /**
    * But Array's Object envelope
    * knows about them:
    */
    //alert("^^^CDATA^^^" in arr); // true


    /**
    * Array can hold up to 4294967295 indexed elements
    * (which is 32 bit unsigned minus one bit for the length flag).
    * This means that the maximum index you can use in array is
    * 4294967294
    */
    //arr[4294967294] = "foobar";
    //alert(arr.length); // 4294967294

    /**
    * An integer bigger than 4294967294 or lesser than 0
    * (so it cannot be used as an array index) turns on
    * JavaScript Baby Care mechanics. Instead of simply break the
    execution
    * with "Invalid array index value" message as any other language would
    do,
    * interpreter switches the object from Array-mode to Hashtable-mode,
    * converts argument from number to string and adds new key to the
    hash.
    * Naturally array doesn't know about it, exactly as Dr. Jekyll had
    nothing
    * but to guess what Mr. Hyde this time did.
    * Also valuable cycles are being spent for all this marry-go-round.
    */
    //arr[4294967294 + 1] = "foobar";
    //alert(arr.length); // 0
    //alert(4294967295 in arr) // true

    /**
    * The same as above happens if argument number but not an integer.
    * Also valuable cycles are being spent for all this marry-go-round.
    */
    //arr[1.5] = "bar";
    //alert(arr.length); // 0


    /**
    * Serving a string index to array turns on
    * JavaScript Baby Care mechanics also. First interpreter
    * attempts to convert the string into valid index value.
    * If it's possible: then the situation gets really ambigious:
    * hell does user want to add "33" property or array[33] ?!?
    * To cover all holes, interpreter both add new array element [33]
    * and new property "33".
    * Needless to say that a create amount of cycles goes for this
    * thinking and arrangement.
    */
    //arr["33"] = "foo";
    //alert(arr.length); // 34
    //alert("33" in arr) // true


    /**
    * If string value is not convertable into a valid array index,
    * interpreter simply switches object from Array-mode to
    * Object-mode and adds new property to the Object envelope.
    * Still cycles are being vasted unless you really wanted to add
    * new property to your array.
    */
    arr["foo"] = "bar";
    alert(arr.length); // 0
    alert("foo" in arr) // true

    /**
    * These are all very basics above you need to understand
    * clearly before to deal with code benchmarks: otherwise
    * they will be one huge unresolved mistery to you.
    * And naturally JavaScript Baby Care has absolutely nothing
    * to do with Hashtable or Array nature, same way as its typeless
    * has nothing to do with String or Number nature.
    */

    }

    function testIE() {
    test();
    }

    function testFF() {
    test();
    }

    window.onload = init;
    </script>

    <style type="text/css">
    body {background-color: #FFFFFF}
    var {font: normal 10pt Verdana, Geneva, sans-serif;
    color: #0000FF; text-decoration: underline;
    cursor: hand; cursor:pointer}
    </style>

    </head>

    <body>

    <noscript>
    <p><font color="#FF0000"><b>JavaScript disabled:-</b><br>
    <i><u>italized links</u></i> will not work properly</font></p>
    </noscript>

    <!--[if gte IE 5]>
    <p>
    <var onclick="testIE()">Test</var>
    </p>
    <![endif]-->
    <![if ! gte IE 5]>
    <p>
    <var onclick="testFF()">Test</var>
    </p>
    <![endif]>

    </body>
    </html>
     
    VK, Nov 12, 2005
    #13
  14. VK

    VK Guest

    Sorry for typo in the testcase I posted before (I had to extract parts
    from a bigger sample).

    Statements:

    obj["^^^CDATA^^^"] = "foo";
    arr["^^^CDATA^^^"] = "foo";

    must be in the init() function and uncommented.


    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <html>
    <head>
    <title>Test Template</title>
    <meta http-equiv="Content-Type" content="text/html;
    charset=iso-8859-1">

    <script type="text/javascript">

    var obj = {};
    var arr = [];

    function init() {
    obj["^^^CDATA^^^"] = "foo";
    arr["^^^CDATA^^^"] = "foo";
    }

    function test() {

    /**
    * Each block below should be uncommented
    * separately before testing and commented
    * back before moving to the next block
    */


    /**
    * Both Hashtable (used for Object) and Array
    * accept CDATA literals as property name:
    */
    //alert(obj["^^^CDATA^^^"]); // "foo"
    //alert(arr["^^^CDATA^^^"]); // "foo"


    /**
    * Array neither counts its properties
    * as array elements nor it knows anything
    * about them:
    */
    //alert(arr.length); // 0

    /**
    * But Array's Object envelope
    * knows about them:
    */
    //alert("^^^CDATA^^^" in arr); // true


    /**
    * Array can hold up to 4294967295 indexed elements
    * (which is 32 bit unsigned minus one bit for the length flag).
    * This means that the maximum index you can use in array is
    * 4294967294
    */
    //arr[4294967294] = "foobar";
    //alert(arr.length); // 4294967294

    /**
    * An integer bigger than 4294967294 or lesser than 0
    * (so it cannot be used as an array index) turns on
    * JavaScript Baby Care mechanics. Instead of simply break the
    execution
    * with "Invalid array index value" message as any other language would
    do,
    * interpreter switches the object from Array-mode to Hashtable-mode,
    * converts argument from number to string and adds new key to the
    hash.
    * Naturally array doesn't know about it, exactly as Dr. Jekyll had
    nothing
    * but to guess what Mr. Hyde this time did.
    * Also valuable cycles are being spent for all this marry-go-round.
    */
    //arr[4294967294 + 1] = "foobar";
    //alert(arr.length); // 0
    //alert(4294967295 in arr) // true

    /**
    * The same as above happens if argument number but not an integer.
    * Also valuable cycles are being spent for all this marry-go-round.
    */
    //arr[1.5] = "bar";
    //alert(arr.length); // 0


    /**
    * Serving a string index to array turns on
    * JavaScript Baby Care mechanics also. First interpreter
    * attempts to convert the string into valid index value.
    * If it's possible: then the situation gets really ambigious:
    * hell does user want to add "33" property or array[33] ?!?
    * To cover all holes, interpreter both add new array element [33]
    * and new property "33".
    * Needless to say that a create amount of cycles goes for this
    * thinking and arrangement.
    */
    //arr["33"] = "foo";
    //alert(arr.length); // 34
    //alert("33" in arr) // true


    /**
    * If string value is not convertable into a valid array index,
    * interpreter simply switches object from Array-mode to
    * Object-mode and adds new property to the Object envelope.
    * Still cycles are being vasted unless you really wanted to add
    * new property to your array.
    */
    arr["foo"] = "bar";
    alert(arr.length); // 0
    alert("foo" in arr) // true

    /**
    * These are all very basics above you need to understand
    * clearly before to deal with code benchmarks: otherwise
    * they will be one huge unresolved mistery to you.
    * And naturally JavaScript Baby Care has absolutely nothing
    * to do with Hashtable or Array nature, same way as its typeless
    * has nothing to do with String or Number nature.
    */

    }

    function testIE() {
    test();
    }

    function testFF() {
    test();
    }

    window.onload = init;
    </script>

    <style type="text/css">
    body {background-color: #FFFFFF}
    var {font: normal 10pt Verdana, Geneva, sans-serif;
    color: #0000FF; text-decoration: underline;
    cursor: hand; cursor:pointer}
    </style>

    </head>

    <body>

    <noscript>
    <p><font color="#FF0000"><b>JavaScript disabled:-</b><br>
    <i><u>italized links</u></i> will not work properly</font></p>
    </noscript>

    <!--[if gte IE 5]>
    <p>
    <var onclick="testIE()">Test</var>
    </p>
    <![endif]-->
    <![if ! gte IE 5]>
    <p>
    <var onclick="testFF()">Test</var>
    </p>
    <![endif]>

    </body>
    </html>
     
    VK, Nov 12, 2005
    #14
  15. VK

    VK Guest

    > Thomas 'PointedEars' Lahn wrote:
    > <http://www.mozilla.org/js/language/E262-3.pdf>
    > ... and a bunch of quotes


    To Thomas 'PointedEars' Lahn and to anyone who wants to prove its
    position by quoting ECMA: this argument is not accepted unless proven
    by test (like my position in the previous post is).

    Otherwise you're in rather stupid position of a person who's meeting
    the Magellan's ship arrival and who's quoting Aristot Earth model to
    them to prove that their trip was absolutely impossible so it stays
    impossible.

    (Please - ECMA writing is not Aristot lore so I'm not a Magellan of any
    kind, just a free associattion).
     
    VK, Nov 12, 2005
    #15
  16. VK wrote:
    >> Lasse Reichstein Nielsen wrote:
    >> There is no casting anywhere. In Javascript, arrays *are*
    >> objects, and their numbered properties are just that: object
    >> properties. The only "magic" in arrays are in the internal
    >> [[put]] method, which keeps the "length" property in sync
    >> with the numbered properties. A literal implementation of
    >> the ECMAScript specification of objects would use the same
    >> [[get]] method for arrays and non-array objects.

    >
    > Sorry but that's an urban legend


    Which is an urban legend? That there is no casting? There is not. That
    Arrays are Objects? They are. That the numbered properties of an array
    are object properties? they are. That the only 'magic' is in the
    internal [[Put]] method of an Array? Well the internal [[Put]] method is
    a specification mechanism, it explains the behaviour it does not
    constrain the implementation. Or that a literal implementation of
    ECMAScript would use the same [[Get]] method? It would, but
    implementations don't have to be literal, they just have to behave as if
    they were literal.

    People will find it much easier to correct your misconceptions if you
    could clearly state what they are instead of making vague references to
    wide ranging blocks of text.

    > greatly dispropaganded in the 3rd
    > edition of my


    Without the ability to pin down and state what you are trying to
    disprove it is unlikely that you will achieve anything, except spreading
    more confusion and misconceptions.

    > <http://www.geocities.com/schools_ring/ArrayAndHash.html>
    > and it will be completely busted in the 4th one I'm hoping
    > to finish before Christmas. To facilitate the cultural shock
    > some people may experience :) here a piece of tast cases


    It would be better to present all of a test case rather than just a
    piece of it as that may enable people to work out what it is exactly
    that you are going on about this time.

    > directly related to the current OP. You are welcome to put
    > each position into your own benchmark test.
    > All comments are inside.
    >
    > <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    > <html>
    > <head>
    > <title>Test Template</title>
    > <meta http-equiv="Content-Type" content="text/html;
    > charset=iso-8859-1">
    >
    > <script type="text/javascript">
    >
    > var obj = {};
    > var arr = [];
    >
    > function init() {
    > }
    >
    > function test() {
    >
    > /**
    > * Each block below should be uncommented
    > * separately before testing and commented
    > * back before moving to the next block
    > */
    >
    >
    > /**
    > * Both Hashtable (used for Object) and Array
    > * accept non-ECMA naming compliant literals as property name:


    ECMA 262 places no restrictions upon the character sequences used as
    property names. The only restriction is that only property names that
    correspond with the formal definition of an Identifier may be used with
    dot notation property accessors. Bracket notation property accessors
    have no such restrictions.

    > */
    > //obj["^^^CDATA^^^"] = "foo";
    > //arr["^^^CDATA^^^"] = "foo";
    > //alert(obj["^^^CDATA^^^"]); // "foo"
    > //alert(arr["^^^CDATA^^^"]); // "foo"


    100% in accordance with the behaviour specified in ECMA 262.

    > /**
    > * Array neither counts its properties
    > * as array elements nor it knows anything
    > * about them:


    That is too incoherent to convey meaning.

    > */
    > //alert(arr.length); // 0


    100% in accordance with the behaviour specified in ECMA 262.

    > /**
    > * But Array's Object envelope
    > * knows about them:


    What is an object "envelope"?

    > */
    > //alert("^^^CDATA^^^" in arr); // true


    100% in accordance with the behaviour specified in ECMA 262.

    > /**
    > * Array can hold up to 4294967295 indexed elements
    > * (which is 32 bit unsigned minus one bit for the
    > length flag).


    What length 'flag'? do you mean the length property?

    > * This means that the maximum index you can use in array is
    > * 4294967294
    > */
    > //arr[4294967294] = "foobar";
    > //alert(arr.length); // 4294967294


    100% in accordance with the behaviour specified in ECMA 262.

    > /**
    > * An integer bigger than 4294967294 or lesser than 0
    > * (so it cannot be used as an array index) turns on
    > * JavaScript Baby Care mechanics.


    Nothing is 'turned on', the behaviour is as specified and applies in all
    cases.

    > Instead of simply break the execution
    > * with "Invalid array index value" message as any
    > other language would do,


    Well they are not invalid array indexes they are _not_ array indexes so
    they re treated as property names when used to add properties to an
    object that is also an Array.

    > * interpreter switches the object from Array-mode to
    > Hashtable-mode,


    Do you have any evidence for any switching? The specified behaviour is
    that an Array is an object so it exhibits object behaviour when property
    names do not qualify as array indexes.

    > * converts argument from number to string and adds new key
    > to the hash.
    > * Naturally array doesn't know about it, exactly as Dr. Jekyll
    > had nothing
    > * but to guess what Mr. Hyde this time did.
    > * Also valuable cycles are being spent for all this
    > marry-go-round.
    > */
    > //arr[4294967294 + 1] = "foobar";
    > //alert(arr.length); // 0


    100% in accordance with the behaviour specified in ECMA 262.

    > //alert(4294967295 in arr) // true


    100% in accordance with the behaviour specified in ECMA 262. But I
    thought you said that this array object did not know about properties
    added with non-array index property names? This array object is
    asserting that it has such a property.

    > /**
    > * The same as above happens if argument number but not an
    > integer.
    > * Also valuable cycles are being spent for all this
    > marry-go-round.
    > */
    > //arr[1.5] = "bar";
    > //alert(arr.length); // 0


    100% in accordance with the behaviour specified in ECMA 262.

    > /**
    > * Serving a string index to array turns on
    > * JavaScript Baby Care mechanics also.


    Nothing is 'turned on' as the behaviour is inherent in the array object.

    > First interpreter
    > * attempts to convert the string into valid index value.
    > * If it's possible: then the situation gets really ambigious:
    > * hell does user want to add "33" property or array[33] ?!?


    They are equivilent.

    > * To cover all holes, interpreter both add new array
    > element [33]
    > * and new property "33".


    When they are both the same thing the interpreter cannot do 'both'. Only
    one property is added to the object.

    > * Needless to say that a create amount of cycles goes
    > for this
    > * thinking and arrangement.
    > */
    > //arr["33"] = "foo";
    > //alert(arr.length); // 34
    > //alert("33" in arr) // true


    100% in accordance with the behaviour specified in ECMA 262.

    > /**
    > * If string value is not convertable into a valid array
    > index,
    > * interpreter simply switches object from Array-mode to
    > * Object-mode and adds new property to the Object envelope.


    So that would be another assertion of 'switching' where none is evident
    and 'envelopes' with no explanation or justification for the use of this
    made-up term.

    > * Still cycles are being vasted unless you really wanted
    > to add
    > * new property to your array.
    > */
    > arr["foo"] = "bar";
    > alert(arr.length); // 0
    > alert("foo" in arr) // true


    100% in accordance with the behaviour specified in ECMA 262.

    > /**
    > * These are all very basics above you need to understand
    > * clearly before to deal with code benchmarks: otherwise
    > * they will be one huge unresolved mistery to you.

    <snip>

    What exactly is a sequence of demonstrations of arrays behaving in
    accordance with the formal specification supposed to demonstrate?
    Particularly, what it is supposed to demonstrate that suggests that
    Lasse's comments are an urban legend?

    All this does is suggest that you are still suffering form fundamental
    misconceptions about the nature of javascript.

    Richard.
     
    Richard Cornford, Nov 13, 2005
    #16
  17. Thomas 'PointedEars' Lahn <> writes:

    > Lasse Reichstein Nielsen wrote:
    >> All properties are equal on objects, arrays or not.

    >
    > No, see <>.


    That doesn't disagree with how I meant it to be understood :)

    When a property (i.e., a name/value pair) has been created on an
    object, it doesn't matter if it is on an array or a non-array
    object. The [[Get]] method is the same in both cases, as is
    [[HasProperty]] and [[Delete]], which are all you can do with the
    existing property.

    >> [...]
    >> Only when assigning to properties on an array is there a difference,
    >> and only when assigning to a property name that is the canonical form
    >> of an array index or is "length".

    >
    > Certainly not.


    From section 8.6.2:

    | For native objects the [[Get]], [[Put]], [[CanPut]],
    | [[HasProperty]], [[Delete]] and [[DefaultValue]] methods behave as
    | described in described in sections 8.6.2.1, 8.6.2.2, 8.6.2.3,
    | 8.6.2.4, 8.6.2.5 and 8.6.2.6, respectively, except that Array
    | objects have a slightly different implementation of the [[Put]]
    | method (section 15.4.5.1).

    Only the [[Put]] method on arrays makes arrays different from other
    objects wrt. property access, and only when putting a value.

    Reading the algorithms for [[Put]] on non-array objects and on array
    objects, the array-version only acts differently if the property name
    is "length" or if it is an array index (a numeral that is the
    canonical form of an integer in the range 0 .. 2^32-2).

    So, yes, all properties on objects are equal, arrays or not. The only
    difference is what happens when you assign to a property of an array
    with a name that is an array index or is "length".


    > Where is this backed up by ECMAScript 3 as an allowed optimization
    > for a compliant implementation?


    That would be:

    | 5.2 Algorithm Conventions
    | The specification often uses a numbered list to specify steps in an
    | algorithm. These algorithms are used to clarify semantics. In
    | practice, there may be more efficient algorithms available to
    | implement a given feature.

    An implementation doesn't have to follow the algorithms from the
    ECMAScript standard, it just has to give the same result. As such,
    all semantics preserving optimizations are allowed.

    /L
    --
    Lasse Reichstein Nielsen -
    DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
    'Faith without judgement merely degrades the spirit divine.'
     
    Lasse Reichstein Nielsen, Nov 13, 2005
    #17
  18. "VK" <> writes:

    [arrays are objects, their elements are object properties, only the
    [[Put]] method on objects makes it differ from other objects ...
    according to ECMAScript]

    > Sorry but that's an urban legend


    It's what the ECMAScript standard specifies. It is all you can assume
    about ECMAScript implementations in general. Specific implementations
    might have certain characteristics that you can discover and use, e.g.,
    an underlying implementation that is more or less efficient for numbers
    than for strings. But it's not something you can rely on between
    implementations.

    ....
    > var obj = {};
    > var arr = [];

    ....

    All examples are consistent with ECMAScript, and what I said, so it is
    only the timing of the implementation that can be discussed.

    I agree that your description probably matches the internal model of
    both IE, Mozilla and Opera's Javascript engines, to some extend.
    There are differences between them that are probably also important.


    If timing is really important, and has been shown to be so, not just
    guessed at, I recommend fixing on a fe, browsers and testing
    there, and then allowing the code to be slower on unknown or unexpected
    browsers. Premature optimization is the root of all evil.

    /L
    --
    Lasse Reichstein Nielsen -
    DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
    'Faith without judgement merely degrades the spirit divine.'
     
    Lasse Reichstein Nielsen, Nov 13, 2005
    #18
  19. Lasse Reichstein Nielsen wrote:

    > Thomas 'PointedEars' Lahn <> writes:
    >> Lasse Reichstein Nielsen wrote:
    >>> All properties are equal on objects, arrays or not.

    >>
    >> No, see <>.

    >
    > That doesn't disagree with how I meant it to be understood :)
    >
    > When a property (i.e., a name/value pair) has been created on an
    > object, it doesn't matter if it is on an array or a non-array
    > object. The [[Get]] method is the same in both cases, as is
    > [[HasProperty]] and [[Delete]], which are all you can do with the
    > existing property.


    And how does the first paragraph of the Array object specification fit in?
    There is clearly either replacing or additional property handling defined
    for those objects, see below.

    >>> [...]
    >>> Only when assigning to properties on an array is there a difference,
    >>> and only when assigning to a property name that is the canonical form
    >>> of an array index or is "length".

    >>
    >> Certainly not.

    >
    > From section 8.6.2:
    >
    > | For native objects the [[Get]], [[Put]], [[CanPut]],
    > | [[HasProperty]], [[Delete]] and [[DefaultValue]] methods behave as
    > | described in described in sections 8.6.2.1, 8.6.2.2, 8.6.2.3,
    > | 8.6.2.4, 8.6.2.5 and 8.6.2.6, respectively, except that Array
    > | objects have a slightly different implementation of the [[Put]]
    > | method (section 15.4.5.1).
    >
    > Only the [[Put]] method on arrays makes arrays different from other
    > objects wrt. property access, and only when putting a value.
    > [...]


    The specification seems to produce a contradiction by itself here.
    In section 8.6.2 in restricts the difference to the [[Put]] method,
    in section 15.4 it specifies "special treatment to a certain class
    of property names."

    >> Where is this backed up by ECMAScript 3 as an allowed optimization
    >> for a compliant implementation?

    >
    > That would be:
    >
    > | 5.2 Algorithm Conventions
    > | The specification often uses a numbered list to specify steps in an
    > | algorithm. These algorithms are used to clarify semantics. In
    > | practice, there may be more efficient algorithms available to
    > | implement a given feature.
    >
    > An implementation doesn't have to follow the algorithms from the
    > ECMAScript standard, it just has to give the same result. As such,
    > all semantics preserving optimizations are allowed.


    ACK


    PointedEars
     
    Thomas 'PointedEars' Lahn, Nov 13, 2005
    #19
  20. VK

    VK Guest

    > Richard Cornford wrote:
    > 100% in accordance with the behaviour specified in ECMA 262.


    I'm not arguing with you any more. There are reasons to argue only if
    the final aim is to find the true between each other arguments. It's a
    vasted time if any fact is accepted if, and only if, it fits to the
    books of canon.

    Honnest the God I did not plan to make a trolling thread here - I
    really wanted to find the most productive solution for my methods.
    Unfortunately I have to conclude that I'm on my own in that as everyone
    else is using wrong model, that gives totally wrong benchmark
    predictions and totally wrong explanations (or no explanation at all)
    to the benchmark results. That would be like asking someone who's using
    flat model of Earth for an advise of the best way from Europe to China
    through America.

    "The great tragedy of science - the slaying of a beautiful hypothesis
    by an ugly fact."
    T.H. Huxley
     
    VK, Nov 13, 2005
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Michael B Allen

    Hash Map API Preference

    Michael B Allen, Nov 18, 2003, in forum: C Programming
    Replies:
    8
    Views:
    440
    CBFalconer
    Nov 19, 2003
  2. rp
    Replies:
    1
    Views:
    537
    red floyd
    Nov 10, 2011
  3. Anthony Martinez
    Replies:
    4
    Views:
    275
    Robert Klemme
    Jun 11, 2007
  4. Michal Suchanek
    Replies:
    6
    Views:
    233
    Nobuyoshi Nakada
    Jun 13, 2007
  5. Srijayanth Sridhar
    Replies:
    19
    Views:
    626
    David A. Black
    Jul 2, 2008
Loading...

Share This Page