Are JS native objects associative arrays?

Asked

Viewed 2,365 times

17

And the arrays are like native objects of JS?

What about literal strings/primitive data? What I understand is that they are instances of the object string, but with the difference of being arrays indexed, correct?

I’m having trouble understanding the concepts of array x object. It seems that this is more subjective than concrete.

  • 1

    I don’t like JS much so maybe I’m talking nonsense but even the Arrays themselves exist in JS. There are Objects that represent data collections and have prototyped properties and methods. What we commonly know as the associative array, would be the hash maps, who are also nothing more than objects.

  • Give me a source in Portuguese that explains about prototyping, please? ^^

  • @ropbla9 Serve this one? "How prototypes work in Javascript?" In fact, there seems to be no practical difference between an object and an array, except that it has Array as a prototype. I think if you create a normal object with the prototype Array (or Array.prototype, don’t know) and a property length it would behave exactly like an array. I’ll take a test...

  • P.S. No, in fact some operations applied in an array (like adding new elements in the form arr[indice] = elemento;) update their index, while in any object this does not occur, regardless of their prototype. They’re really different guys, per se.

  • They are not different types (under the specification). Actually arrays are a peculiar subtype of object, @mgibsonbr. See http://perfectionkills.com/how-ecmascript-5-still-does-not-allow-to-subclass-an-array/

  • @bfavaretto If it’s a subtype it’s a different kind, right? : I took a look at the link you indicated, and it is precisely because of some of these observed "phenomena" [when trying to create an array subclass] that I made this statement. But I confess that I myself am not 100% sure, formally speaking.

  • 1

    @mgibsonbr It is that formally only 6 types are defined: String, Number, Boolean (the primitives), Null, Undefined and Object. Arrays and functions are treated as special cases.

Show 2 more comments

2 answers

12


TL;DR

One can understand that they are but in reality it is not quite so. It was created to give this appearance although the implementation is not quite that. Strings too. It depends on whether you are looking at the implementation or the formal concept.

Concepts

Something can be subjective and concrete, these concepts are not antagonistic. In this case the functioning is objective and concrete. The concept may be a little more abstract, although objective. But every concept is an abstraction.

Maybe you mean understanding this isn’t important. To do the basics doesn’t really matter but when you get creative, you want to go beyond rice and beans, understand this is critical. Only the total specialization allows to explore a language that has few abstractions but great possibilities to create its own, that says the thousands of frameworks servants.

I’m not a deep language scholar and answers are likely to come up better than mine.

Detailing

You’re right, the objects in JS are arrays associative or hashes or dictionaries or maps as can also be called (although technically we cannot classify so in the case of Javascript that only allows type keys String). This simplified the creation of the language. At least the implementation is done with them.

So yes, these arrays are understood by language natively. But they are understood as objects and not as arrays. They are a little more than syntax sugar for arrays. There is an understanding of language in how objects work. A syntax can be partially exchanged giving power and flexibility in various aspects. Note that formally JS only possesses "natively" the type Object. It works like a array associative but not considered a, formally speaking.

What prevents a type to have a more concrete implementation but to be recognized in a more abstract way? This is the basis of modern programming (for good or for evil).

String

You got to think of the kind String in two ways. There is an abstract type that encapsulates a string (remembering that in JS each variable can be of any type and even can change the type but the data, the value itself does not change type ever, if you think that changed the type, changed the data). Concretely this object has its properties in keys associated to a array. One of these properties is the text of string properly said (which is still another abstraction since a text is nothing more than a array of characters). The language has some extra understandings with this object. It is not just any object created by the user, it is something that has greater relevance to the language. There is a special treatment for this type.

String can be used more conventional as an object:

var x = "texto"; //ajudado pela linguagem como string
var y = new String("texto"); //ajudado pela linguagem como objeto

But note that there are differences. The first form is optimized. The second one works more like a normal object. The recommendation is not to use the second form.

If this is what you think something can be considered native about, then I think it became clearer, the language has a greater understanding of some types of data defined in it and can give a special treatment. But all types tend to be used as if they were normal objects. Most likely the way the properties and methods of primitive types are accessed is different from a "normal" object but in appearance, in abstraction, it is almost the same thing.

Implementation

Evidently the exact way it is implemented is a detail of implementation. Each interpreter/compiler can do as they see fit as long as it meets all the language requirements that every user expects. For this there is a language specification.

Note that I’m not saying that all Javascript objects are implemented exactly as if they were arrays associative language, even because there are no arrays associative in the language specification. The syntax actually allows accessing data from an object as if it were arrays but there is a difference of internal implementation.

When you create a Object you can’t make a push() or a sort() or access .length of the object structure (of course its type may have one of the properties with this name) that is possible to do in a Array (a type that is not part of the language but part of the library). They are different types that work similarly. We can say that an object is a array-like but not the kind Array even.

The same goes for String, it seems but she’s not just one Array with properties and one of these properties is another Array of characters (JS neither has the concept of single character as in other languages, a character alone does not cease to be a string).

But you can sweep (with for in) all elements of an object as if it were one Array. You can do the same with a text, character by character. But this does not make them a Array normal language, it is still a Object.

Do not confuse an object in general terms with a Array. Of course the guy Array does not cease to be an object, it comes from the same prototype of Object but the opposite is not true. A Object any is not built with a Array, even because you would have an egg and chicken problem. The same goes for String. How objects need to strings for your keys the type String could not depend on the Object to exist.

var meuObjeto = { a: 1, "b": 2 };
for (var chave in meuObjeto) console.log("key " + chave + "; value " + meuObjeto[chave]);
console.log("tipo: " + typeof(meuObjeto));

I put in the Github for future reference.

Completion

There is confusion there between the concrete implementation, which is based on array associative and the formal concept that treats these arrays as objects and only.

But I’ve seen other definitions on the subject. I imagine this has to do with the fact that there are different implementations. Therefore, in general (but not in all cases), it is not important to understand the implementation but the abstraction exposed in the standard language. What you need to understand is that the properties of an object can be accessed in the same way as it is done in a array associative and this brings advantages, makes the language more dynamic.

See the object list built-in on MDN. Doesn’t mean they’re all part of the language.

  • 1

    There could be no better answer than yours. I understood a more than satisfactory percentage and it saved much of my time. If I had how I would score certain 1000x, however I can only thank you from my heart, haha.

  • @ropbla9 can yes, I think it will even show up. Anyway read everything you can on the subject. Already has great information in the mgibsonbr response. I will improve mine. There are some things that are unclear and I am researching (p/my benefit the best questions are the ones that make me research) to complement.

7

I don’t know what you mean by "associative array", but the fact is that in Javascript every "object" type can receive properties whose key is textual. Arrays are objects, but strings are not always (see maniero’s response for more details).

var tipos = [0, 0.0, true, "teste", new String("teste"), [], {}, /regex/, function() { }];
tipos.forEach(function(dado) {
  dado.foo = "bar";
  $("<tr></tr>")
      .append("<td>" + dado + "</td>")
      .append("<td>" + typeof dado + "</td>")
      .append("<td>" + (dado.foo == "bar") + "</td>")
      .appendTo($("table tbody"));
});
// null e undefined lançariam uma exceção no teste acima
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table>
  <tr><th>Dado</th><th>typeof</th><th>Propriedades arbitrárias?</th></tr>
</table>

By the way, all key is textual, only. If you do array[0] = 10 That’s the same as doing array["0"] = 10, for all purposes. Similarly, you cannot use a complex object as a key (unlike a dictionary or map more general, as we have in other languages) because it will be converted into string before being inserted:

function log(texto) {
  $("<p>" + texto + "</p>").appendTo($("#saida"));
}

var arr = [];
log(arr.length); // 0
arr[0] = 10;
log(arr.length); // 1
arr["1"] = 20;
log(arr.length); // 2
arr.push(30);
log(arr.length); // 3
log(JSON.stringify(arr)); // [10, 20, 30]

var obj = {};
obj.foo = 10;
obj["bar"] = 20;
obj[{ um:"objeto" }] = 30;
obj[{ outro:"objeto" }] = 40;
log(JSON.stringify(obj)); // { "foo":10, "bar": 20, "[object Object]":40 }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="saida"></div>

In the near future, there will be support for a Map proper (i.e. using any object as a key), but common objects only accept strings, or convert whatever is passed to the subscript into a string before using.

As for accessing strings as arrays, I’m not sure how it is specified, but in practice accessing an index of a string returns a substring with a single character:

var str = "abc";
var ch = str[1];
typeof ch; // string
ch == "b"; // true

Use str.charAt(indice) produces the same result.

If you want the "characters" themselves, one way is to get the code Units (16 bits) using the method str.charCodeAt(indice), that returns the character as an integer (in Ecmascript 6 there will also be the str.codePointAt(indice), this returning any code point including us Smps). The reverse process can be done via String.fromCharCode(inteiro, ...) (or String.fromCodePoint(...)).

Browser other questions tagged

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