What does mutable keyed collection mean in javascript? - javascript

I am reading the book JavaScript: The Good Parts. It is said that
Objects in JavaScript are mutable keyed collections.
What does mutable keyed collection mean?
AS far as I could find on internet, mutable means the vales can be changes. I couldn't find what keyed collection mean.

Objects are a collection of keys with associated values. This could be referred to as a "keyed collection":
var o = {
foo: "bar",
bar: "baz"
}
(Where foo and bar here are keys).
...which can be changed (as you've already said, the "mutable" part):
o.foo = "foobar";
o.foobar = "bar";

The keyed keyword here means that the data is "named", "indexed" or "keyed".
{
key : value,
key2: value2
}
a collection because it contains a collection of data.

It is about the way objects work in Javascript, they behave like C# Dictionaries, for example, or named arrays in PHP. obj.someKey is equivalent to obj['someKey'] and you can always change the values associated with those keys or indeed delete them.
More advanced: the key uniquely identifies the value stored with it and the system is optimized for performance, so you can use this to index information or to get distinct values of a list,etc.

Related

Object or array for the project

I have two variants to work with my objects full of data:
let global_obj = {
"id0": { /*big object 0*/},
"id1": { /*big object 1*/},
"id2": { /*big object 2*/}
};
and:
let global_arr = [
{ id: "id0" /*big object 0*/},
{ id: "id1" /*big object 1*/},
{ id: "id2" /*big object 2*/}
];
So I can save my big objects full of data inside of a global array or a global object. Which way is better in terms of performace (looping through, deleting, adding new objects)?
I am going to address specific objects by their id very often, change objects' properties, loop trought them all.
I would use an object in this case as finding an element by id is easier/faster. If index/order of elements is important, object don't help here and you need to use an array.
Basically:
Objects: Keyed collections
Arrays: Ordered collections
But regular objects and arrays are not the only options if the environment supports ES2015. ES2015 has introduces several APIs for working with collections: Map, Set, WeakMap and WeakSet.
As you mentioned that you'll be "addressing specific objects through their id's very often"; using an Object will be a wise choice for you. Since accessing an object's key is done in O(1) as compared to finding the object in an array, which will be O(n), hence Object will be better in performance.
You should do what's more convenient for you, it most likely won't make a difference.
However, generally, if the top level object is small, the array is always faster than a hashtable/object (the size of the inner objects doesn't matter). If the top-level structure is big, then you should consider the big-o complexity for the operations you want to perform on the top-level structure. See http://bigocheatsheet.com/

What is happening under the hood in javascript when using the Array brackets notation

I have generally found javascript to be transparent, in that there are very few black boxes where "magic" just happens and you should just accept and look the other way, however I have not found any answer to how the Array brackets [] notation actually works under the hood.
let arr = [4, 5, 6, 7]
console.log(arr[3]) // <- How does this work?
What is javascript doing to access the item at index 3. Does it internally call some method on the Array.prototype?
With an object, the [] is a shortcut for a property accessor.
let obj = {
a: 'hello',
b: 'world'
}
obj['a'] === obj.a // true
Is an array then just an object with a long list of integer based properties?
let objArray = {
0: 'hello',
1: 'world'
}
let realArray = ['hello', 'world']
objArray[0] === 'hello' // true
realArray[0] === 'hello' // true
objArray.0 // SyntaxError: Unexpected number
realArray.0 // SyntaxError: Unexpected number
I have seen many many online discussions that all come to the conclusion that you cannot overload the brackets notation to truly subclass an Array but I have never seen an explanation on what magic is happening under the hood that allows the Array to work the way it does.
The obvious follow up question is whether there is any way to intercept the bracket notation access to define your own behavior, but I think I already know the answer to that.
You'd probably have to look at the implementation code to know precisely what's going on, but the basic idea is that arrays are actually layered atop objects.
This is backwards:
With an object, the [] is a shortcut for a property accessor.
The bracket notation is more fundamental. Thus, obj['foo'] and obj.foo work the same, but there is no equivalent for obj['foo & bar'], which is perfectly legitimate, and will respond with a value if obj has a key named "foo & bar".
Is an array then just an object with a long list of integer based properties?
Not quite, but you're not far off. Arrays are objects with the Array prototype, and with a little bit of additional magic to set the length property when new keys are added, or remove keys when that length is set.
And no, you cannot override the [] operator for your own purposes.
Is an array then just an object with a long list of integer based properties?
Yes, in it's simplest form, an Array is an Object with a list of integer base properties that is based on the Array prototype (which gives access to all the array methods like map, forEach, etc.)
As for intercepting the bracket notation, no, I have not seen anything that would allow that besides creating your own Object that has the methods you need (and then only access that object via the appropriate methods).
More info from MDN:
Arrays are list-like objects whose prototype has methods to perform traversal and mutation operations. Neither the length of a JavaScript array nor the types of its elements are fixed. Since an array's length can change at any time, and data can be stored at non-contiguous locations in the array, JavaScript arrays are not guaranteed to be dense; this depends on how the programmer chooses to use them. In general, these are convenient characteristics; but if these features are not desirable for your particular use, you might consider using typed arrays.
Arrays cannot use strings as element indexes (as in an associative array) but must use integers. Setting or accessing via non-integers using bracket notation (or dot notation) will not set or retrieve an element from the array list itself, but will set or access a variable associated with that array's object property collection. The array's object properties and list of array elements are separate, and the array's traversal and mutation operations cannot be applied to these named properties.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections#Array_object

Non-functionals of Arrays in JavaScript [duplicate]

The difference between a JavaScript Array, and Object is not very big. In fact it seems Array mainly adds the length field, so you can use both Arrays and Objects as numeric arrays:
var ar = new Array();
ar[0] = "foo";
ar["bar"] = "foo";
var ob = new Object();
ob[0] = "foo";
ob["bar"] = "foo";
assert(ar[0] == ob[0] == ar["0"] == ob["0"] == ar.bar == ob.bar); // Should be true.
So my questions is, in popular JavaScript engines (V8, JavaScriptCore, SpiderMonkey, etc.), how is this handled? Obviously we do not want our arrays to be actually stored as hash maps with key values! How can we be reasonably sure our data is stored as an actual array?
As far as I can see there are a few approaches engines could take:
Array is implemented exactly the same way as Object - as an associative array with string keys.
Array is a special case, with a std::vector-like array backing the numeric keys, and some density heuristic to prevent insane memory use if you do ar[100000000] = 0;
Array is the same as Object, and all objects get a heuristic to see if using an array would make more sense.
Something insanely complicated that I haven't thought of.
Really this would be simpler if there were a proper array type (cough WebGL typed arrays cough).
In SpiderMonkey, arrays are implemented basically as C arrays of jsvals. These are referred to as "dense arrays". However, if you start doing un-array-like things to them -- like treating them like objects -- their implementation is changed to something which very much resembles objects.
Moral of the story: when you want an array, use an array. When you want an object, use an object.
Oh, a jsval is a sort of variadic type which can represent any possible JavaScript value in a 64 bit C type.
In V8 and Carakan (and presumably Chakra), all (non-host) objects (both those that are arrays and those that aren't) with properties whose names are array indexes (as defined in ES5) are stored as either a dense array (a C array containing some value wrapper) or a sparse array (which is implemented as a binary search tree).
The unified object representation shows through in that it affects enumeration order: with an object, SpiderMonkey and SquirrelFish both give all properties in insertion order; and with an array, they in general (there are special cases in SM at least!) array indexes first then all other properties in insertion order. V8, Carakan, and Chakra always give array indexes first then all other properties in insertion order, regardless of object type.

What's the difference between objects and associated array in javascript?

The Confusing discussion
In this question, there is a discussion on the concepts of associated array and object in javaScript which I got a bit confused.
In this example code:
var check = {
pattern : {
name: /^[a-zA-Z-\s]{1,20}$/,
email: /^[a-zA-Z0-9._(-)]+#[a-zA-Z0-9.(-)]+\.[a-zA-Z]{1,4}$/,
pass: /.{6,40}/,
url: /^[(-)\w&:\/\.=\?,#+]{1,}$/,
aml: /<(.+)_([a-z]){1}>$/
}
};
Here is the discussion makes me confused:
#steven.yang the outer object is not an associative array in your sample, but that is what is being asked for
#sissonb what do you mean by 'outer object is not an associative array'? I think associated array is expressed as object in javascript. The difference is in the notation - either through foo.bar or foo[bar]
#steven.yang associated array means key => value. http://en.wikipedia.org/wiki/Associative_array Your inner object has a key of pattern, the object containing this associative array has no key.
My Understanding of Associated Array and Objects in JS
Associated array is defined as key-value pairs which is expressed as the object in JavaScript.
The outer object assigned to check has a key pattern and an value of another object. The inner object has keys of name, email ... and corresponding values of regular expression objects.
Could both objects be counted as associative arrays?
Not really, here's why:
var arr = new Array();
arr["foo"] = 100;
arr["bar"] = 200;
console.log(arr.length); // Prints 0.
Adding elements to an associative array should increase its length (IMO).
It looks and acts (somewhat) like an associative array because of syntactic sugar. What appear to be "array entries", however, are (just) object properties.
If you define "associative array" as a data structure that stores information as a collection of key-value pairs, then yes, JavaScript objects are associative arrays.
However, the phrase "associative array" is not generally used in the context of JavaScript, rather, we say "object". I'd suggest sticking to standard JS terminology to avoid misunderstandings.
Note that JS also has (non-associative) arrays, with elements accessed via numeric indexes. These are also objects and so allow non-numeric key properties, but this is generally considered bad practice.
There are no associative-arrays in JavaScript. Everything is object.
Certainly they are similar but associative-arrays in JavaScript are just objects.
Associative Array
In computer science, an associative array (also called a map or a dictionary) is an abstract data type composed of a collection of (key,value) pairs, such that each possible key appears at most once in the collection.
As far as I know objects in JavaScript match that definition.
Of course there is no unique "Associative Array" object, that's any different then any other normal object. So if you want associative array functionality use a javascript object.
However the following is a common piece of misinformation
There is no associative array in JavaScript
You should simply ignore these people, maybe try to convince them they are wrong.
My response is coming late, but I hope this can help people to understand this difference. I was reading this post and there isn't a satisfactory definition of an associative array.
JavaScript doesn't have Associative Arrays. These are just objects that you can treat as associative arrays for convenience. In objects you store values as named properties, very similar to associative arrays in other programming languages. That's why you can access the properties like an associative array, but with methods associated to objects. You can test creating an object and try all the things you can do with an associative array, but you can't do all the methods of an array.

How do I access the first key of an ‘associative’ array in JavaScript?

I have a js 'associative' array, with
array['serial_number'] = 'value'
serial_number and value are strings.
e.g. array['20910930923'] = '20101102'
I sorted it by value, works fine.
Let's say I get back the object 'sorted';
Now I want to access the first KEY of the 'sorted' array.
How do I do it? I can't think I need an iteration with
for (var i in sorted)
and just stop after ther first one...
thanks
edit: just to clarify, I know that js does not support associative arrays (that's why I put it in high commas in the Title).
2021 Update
Since ES6, properties with string keys are enumerated in insertion order. Here's a nice summary. My original answer from 2010 was correct at the time and is preserved below:
Original answer
JavaScript object properties are specified to have no order, much though many people wish it were different. If you need ordering, abandon any attempt to use an object and use an Array instead, either to store name-value objects:
var nameValues = [
{name: '20910930923', value: '20101102'},
{name: 'foo', value: 'bar'}
];
... or as an ordered list of property names to use with your existing object:
var obj = {
'20910930923': '20101102',
'foo': 'bar'
};
var orderedPropertyNames = ['20910930923', 'foo'];
Try this:
// Some assoc list
var offers = {'x':{..some object...}, 'jjj':{...some other object ...}};
// First element (see attribution below)
return offers[Object.keys(offers)[0]];
// Last element (thanks to discussion on finding last element in associative array :)
return offers[Object.keys(offers)[Object.keys(offers).length - 1]];
Actually JavaScript doesn't support associative arrays, so you can't loop through it in an implied order (e.g. you can't access it via the indexer property array[0] won't access the first element in your object). The syntax is what makes it look like it does, but in reality it doesn't. So you have no "Order" to your objects.
http://www.hunlock.com/blogs/Mastering_Javascript_Arrays
Javascript does not have, and does not
support Associative Arrays. However…
All arrays in Javascript are objects
and Javascript's object syntax gives a
basic emulation of an associative
Array. For this reason the example
code above will actually work. Be
warned that this is not a real array
and it has real pitfals if you try to
use it. The 'person' element in the
example becomes part of the Array
object's properties and methods, just
like .length, .sort(), .splice(), and
all the other built-in properties and
methods.
Just thinking off the top of my head, but could you have another array with the key value pairs swapped?
So the answer would be arrayKeyValueReversed['20101102'] = '20910930923';
When you sort the array, use the first item (array[0]) as the key to get the value in the arrayKeyValueReversed.

Categories