Access negative index from an array

Asked

Viewed 1,130 times

5

BUG?

I was building a library for Arrays treatment and came across the following situation: When including a value to a negative index within my Array, this index does not appear when using some methods:

Example:

var array = new Array("Maria", "João", "Carlos");
array[-3] = "Bernardo";

console.log(array[-3]); //Bernardo
console.log(array.length); //3
console.log(JSON.stringify(array)); //"["Maria", "João", "Carlos"]"

Note that the quantity remains as 3 when using length and the method JSON.stringify shows only the original 3, however, when displaying on the console the array[-3] the name comes correctly.

Question:

It wouldn’t be right to show up length = 4 and appear in the method JSON.stringify? Why does this happen? Would it be some kind of bug the language allow me to add a value to a negative index?

3 answers

7


In Ecmascript (Javascript base and Actionscript) arrays are not "special" in any way: they are just a normal object with an attribute length. It means that:

  • Internally, your keys are strings, not integers:

    var arr = [10, 20, 30];
    console.log(arr[0]);   // 10
    console.log(arr["0"]); // também 10
    
  • You can add any additional property you want:

    var arr = [10, 20, 30];
    arr.teste = 42;
    console.log(arr.teste);    // 42
    console.log(arr["teste"]); // 42
    

In general, objects that have the type Array are in charge of updating their length as numerical (non-negative) properties are added. This occurs regardless of whether they are added with the push, with a numeric index or with a string index:

var arr = [];  // length: 0
arr.push(10);  // length: 1
arr[1] = 20;   // length: 2
arr["2"] = 30; // length: 3
arr[10] = null; // length: 11

But if you add other properties of any kind, he considers that this is just a "normal" property - which has nothing to do with arrays - and does not touch length:

arr.foo = "bar"; // length: 11
arr["foo"] = 42; // length: 11
arr["+"] = 9001; // length: 11
arr["-3"] = 123; // length: 11

This is why one can add elements in a "negative index": because Ecmascript does not consider this as an "index", but only as a normal property.

Examples in jsFiddle. In the Chrome console, it shows not only the indexes positioned but also the "separate" properties. Ex.: [10, 20, 30, 10:null, foo:"bar"]

  • A link to Ecmascript description would be nice! Rsrs. I didn’t know that Javascript and Actionscript were provided with this language, now it becomes even clearer the similarity between them. Regarding Array, I now understand that -3 is treated as "-3" being a value of an Object and not an index of an Array and that the Array object of languages are also a "subtype" of a common object.

  • I also tested with Boolean value array[true] = "Abner;", it treats like a 'normal object'! Very strange and at the same time interesting! Rsrs

  • 1

    @Biio He accepts even null and undefined as keys... : P (huge potential for errors, by the way)

  • 1

    But @biio, note that the key is always converted to string, so "true", "null" or "undefined".

  • 1

    @bfavaretto Indeed. Inclusve, when using an object as a key (say, arr[{ foo:"bar" }]) what is used is its representation as string (arr["[object Object]"]). Another potential for mistakes...

  • 1

    It is. In the next version (ES6), there will be Map and WeakMap, who will accept objects of truth as keys.

Show 1 more comment

2

Javascript arrays have no negative indexes.

What happens here is that you are creating a new property in the object Array, by the name "-3".

The same thing happens if you use a word. For example:

var v = new Array("abra", "cadabra", "alacazan");
v["-5"] = "isto não é um índice";
v["banana"] = "muito menos isto";
v[-7] = "nem isto";

v.length // 3
v["-5"] // "isto não é um ndice" 
v.banana // "muito menos isto"
v["banana"] // "muito menos isto"
v["-7"] // "nem isto"
  • I disagree... When inserting a positive number inside the array, for example array[3] = "Teste", automatically the index 3 of my array appears when using the methods JSON.stringify and array.length... ("["Maria", "João", "Carlos"]" and 4, respectively)

  • 1

    Of course, because 3 is a valid index. "-3" no.

  • @beet t t mean that -3 is seen as the string "-3" at the time of setting the value to index ? then why when I try to error v[-a]? he was supposed to understand it as a string following his line of reasoning.

  • 1

    @Tuyoshivinicius 1 is also seen as the string "1", but it is a valid index.

  • @Tuyoshivinicius Why -a is ambiguous. The interpreter faces a as a variable. Note that I set, in my example, v[-7] and I stopped v["-7"].

  • Beet, all indexes are strings. See mgibsonbr’s response, are normal properties, but with special treatment.

  • @Tuyoshivinicius where v[-a] gives error? In Chrome at least it works normally...

  • @bfavaretto Yes, I know. I just complemented your comment.

  • @mgibsonbr It may be that your Chrome logs are disabled because here they say that "a" is an undefined reference, which is obviously rsrs https://cdn.anonfiles.com/1407177293387.jpg

  • @Tuyoshivinicius hahaha ok! Is that in my case I defined a... :P (both positive and negative; see jsFiddle at the end of my answer)

Show 5 more comments

1

I found the reply of @mgibsonbr correct but a little confusing. I will leave my contribution, a translation and adaptation of an answer of Soen, which makes it more evident to Javascript donkeys like me. >.<


When you directly reference an index or position, the values are added to the array:

var array = [];

array[0] = "Foo";
array[1] = "Bar";

// Result: ["Foo", "Bar"]
// Length: 2

What is not the case when referencing negative indices:

var array = [];

array[0]  = "Foo";
array[1]  = "Bar";
array[-1] = "Fizzbuzz"; // Índice inválido - Pega, Rex! Pega!

// Result: ["Foo", "Bar"]
// Length: 2

Values will only be added if you play by the rules. If you do not follow them, values will not be added. Simple as that!

But although not accepted as part of the data set, information associated with negative evidence is accepted by Array object and so it is still possible to access this value, like any other property:

array[-1]; // "Fizzbuzz"

When we build an Array object, even if we have not defined any value for it, it is not empty; after all, all methods belonging to the object, whether native or prototyped, are already there at disposal and can even be accessed in the same way:

array["pop"]; // function pop() { [native code] }

Here we access the index prop which is not a valid index for data collection, but is valid as property of the Array object and is associated with native code Array.pop().

And so property as length and methods such as Array.prototype.pop() or Array.prototype.Slice(), working solely with integer and positive indices show different results than you expect.

Again, to reinforce. The value is not in the array and yes in the object Array.

  • 1

    I don’t know, it confuses me more to think of "the array" versus "the array object". The two are one thing. The secret is in the length, which is actually a getter and Setter, and not a common property.

  • When rescuing Array items too! Just like transforming Array into JSON! It’s a bit confusing but I understand now that there is an object behind this Array!

  • 1

    On the contrary. In Javascript at least, Array is an object. What we iterate and reference by indexes is a mere collection of data. But yes, you understand. ^_^

Browser other questions tagged

You are not signed in. Login or sign up in order to post.