This question already has answers here:
JavaScript property access: dot notation vs. brackets?
(17 answers)
Closed 5 years ago.
Closely related questions:
associative array versus object in javascript
Why does JavaScript not throw an exception for this code sample?
javascript array associative AND indexed?
I have the following code sample:
var someVariable = {abc: "def", ghi: "jkl"}
someVariable["SomeProperty"] = "dfsdfadsd"
alert(someVariable["SomeProperty"])
var someOtherVariable = { abcd: "defsd", ghij: "dfsdfdss" }
someOtherVariable.SomeOtherProperty = "adfsdfsd"
alert(someOtherVariable.SomeOtherProperty);
alert(someOtherVariable["SomeOtherProperty"])
All of them do exactly what they look like - they attach a property to their respective objects. The alert shows the expected string in every case. My understanding from the related questions is that there's no functional difference between the two.
I also encountered the following statements in W3Schools's JavaScript arrays tutorial:
Many programming languages support arrays with named indexes.
Arrays with named indexes are called associative arrays (or hashes).
JavaScript does not support arrays with named indexes.
In JavaScript, arrays always use numbered indexes.
If that's the case, why is array syntax permitted here at all? (Again, my understanding from the related questions is that the actual distinction between an associative array and a JavaScript object is, at a minimum, slightly blurry, and that that's how JavaScript is implementing object properties "under the hood").
As far as I know (and please correct me if I'm wrong as JavaScript isn't my primary language), it's not possible to do other things you'd expect to be able to do with an array (e.g. iteration with a for loop), so why bother having both syntaxes? In C# you can do something like:
// A C# dictionary is basically an associative array
Dictionary<string, int> dict = new Dictionary<string, int>();
// Fill dictionary ...
foreach (string key in dict.Keys) {
int value = dict[key];
// Do something with the value
}
but I'm not aware of a way to do a similar thing with JavaScript properties. There's a clear necessity for this syntax in C# (keys are definitely not properties of dict), but why does JavaScript have this (given that they're exactly equivalent)? Am I missing something, or is this actually completely redundant?
Why does JavaScript allow array syntax to access properties?
It isn't "array syntax".
Square brackets are a standard way to access the properties of an object.
Arrays are just a type of object.
Square bracket notation has some advantages over dot notation for accessing properties:
You can use any expression to define the name, including variables and function calls.
You can access properties which have names that are invalid in an identifier (such as those which start with a number, which is why you commonly see them used to access arrays).
It's also more verbose and potentially less efficient.
the actual distinction between an associative array and a JavaScript object is, at a minimum, slightly blurry, and that that's how JavaScript is implementing object properties "under the hood"
JavaScript doesn't have a feature called "associative arrays". (W3Schools is not a trustworthy source).
It has objects, which are (at their core) collections of property:value pairs. (This is similar to PHP's associative array feature).
It has arrays, which are objects which inherit from the Array constructor, gaining methods like forEach and properties like length (which uses a getter function to determine its value based on the properties with a name that is the highest integer value).
Related
Are arrays merely objects in disguise? Why/why not? In what way(s) are they (such/not)?
I have always thought of arrays and objects in JS as essentially the same, primarily because accessing them is identical.
var obj = {'I': 'me'};
var arr = new Array();
arr['you'] = 'them';
console.log(obj.I);
console.log(arr.you);
console.log(obj['I']);
console.log(arr['you']);
Am I mislead/mistaken/wrong? What do I need to know about JS literals, primitives, and strings/objects/arrays/etc...?
Are arrays/objects merely strings in disguise? Why/why not? In what way(s) are they (such/not)?
Arrays are objects.
However, unlike regular objects, arrays have certain special features.
Arrays have an additional object in their prototype chain - namely Array.prototype. This object contains so-called Array methods which can be called on array instances. (List of methods is here: http://es5.github.com/#x15.4.4)
Arrays have a length property (which is live, ergo, it auto-updates) (Read here: http://es5.github.com/#x15.4.5.2)
Arrays have a special algorithm regarding defining new properties (Read here: http://es5.github.com/#x15.4.5.1). If you set a new property to an array and that property's name is a sting which can be coerced to an integer number (like '1', '2', '3', etc.) then the special algorithm applies (it is defined on p. 123 in the spec)
Other than these 3 things, arrays are just like regular objects.
Read about arrays in the spec: http://es5.github.com/#x15.4
Objects are an unordered map from string keys to values, arrays are an ordered list of values (with integer keys). That's the main difference. They're both non-primitive, as they're composed of multiple values, which also implies pass-by-reference in JavaScript.
Arrays are also a kind of object, though, so you can attach extra properties to them, access their prototype and so on.
In your revised example, you're only taking advantage of the fact that an array is actually an object, i.e. you can set any property on them. You shouldn't do that. If you don't need an ordered list of values, use a plain object.
Strings can be either primitive or objects, depending on how they were declared.
var str = 'yes';
Gives you a primitive, while,
var str = new String('yes');
will give you a String object.
All arrays are the same (Whether or not they were defined with [] or new Array()), are of the type object and inherit from the "Array" object's prototype. There aren't real classes in Javascript, everything is an object, and there's a system defined object called Array. It has a property called 'prototype' (of type object), and when you use the new keyword on an object with a prototype property, it creates an instance with a reference to the contents of the prototype and stores it in your variable. So all arrays you've ever used in Javascript are objects and instances of Array's prototype property.
In any case, although arrays really are objects, they behave like arrays because of their useful properties and functions (Such as length, slice, push etc).
Another note, although I said there are no classes, when you do this:
console.log(Object.prototype.toString.call(your_object));
it will give you a string in the form [object Object]. But what's useful is that when you call it with an array, you get [object Array] same with functions which give [object Function] and a number of other system defined types, which assists in differentiating between normal objects and arrays (Since the typeof operator will always just return the string 'object').
Try this
var a = Array;
and go into firebug and examine the contents of a, especially it's 'prototype' property.
Edit: Changed the wording a bit, to be more correct. In fact when you use the new keyword, it creates an instance which references the prototype object. So any changes made to the prototype after the instance's declaration, will still affect the instance.
Edit: In answer to your latest revised question (are arrays/objects actually strings in disguise): No. They are objects, as I've explained. Strings are either a primitive type, or an object type (An instance of the String object) which contains the primitive equivalent as one of it's properties.
Arrays are not primitives in Javascript, they are objects. The key difference is that as a result, when you pass an array to a function it is passed by reference, not by value.
So yes! Arrays are objects in javascript, with a full blown Array.prototype and everything (don't touch that though...)
The confusion comes from the fact that javascripts lets you access object attributes in two ways:
myObj.attribute
or
myObj["attribute"]
Really what makes an array an array has nothing to do with the way you store data -- any object can store values using the syntax you use to store the array -- what makes an array an array is the fact that array methods (e.g. shift() and sort()) are defined for Array.prototype.
Trying to be brief with what I believe to be of the most significance: arrays have a number of methods that objects do not. Including:
length
push
pop
An object declared as var x = {foo:bar} has no access to a .length() method. They are both objects but with the array as a sort of superset with methods mentioned as above.
I don't feel I this is even close to being of Crockford standard in terms of explanation but I'm trying to be succinct.
If you want to get some quick results, open up Firebug or your javascript Console and try Array.prototype and Object.prototype to see some details
Update: In your example you declare an array and then do:
foo['bar'] = 'unexpectedbehaviour';
will produce unexpected results and won't be available in simple loops such as:
var foo=[0,1];
foo['bar'] = 2;
for(var i=0;i<foo.length;i++){
console.log(foo[i]);
}
//outputs:
//0
//1
An array can accept foo['bar']=x or foo.bar=y like an object but won't necessarily be available to be looped through as highlighted above.
Not that I'm saying that you can't iterate through the properties of an object, just that when working with an Array, you're utilising that unique functionality and should remember not to get confused.
In JavaScript you have a few types, everything else is an object. The types in JavaScript are: boolean, number, and string. There are also two special values, "null" and "undefined".
So the quest "is a JavaScript array an object?" is slightly ambiguous. Yes, a JavaScript array is an "object" but it is not an instance of "Object". A JavaScript array is an instance of "Array". Although, all objects inherit from Object; you can view the inheritance chain on the MDC. Additionally, arrays have slightly different properties than an object. Arrays have the .length property. They also have the .slice(), .join(), etc methods.
Douglas Crockford provides a nice survey of the language's features. His survey discusses the differences you are asking about. Additionally, you can read more about the difference between literals and constructors in question #4559207.
Arrays are Objects, but of a specialized nature. Objects are collections of values indexed by keys (in Javascript notation, {'key': 'value'}), whereas Arrays are Objects whose keys are numeric (with a few functions and properties). The key difference between them is obvious when you use a for each loop--an Object will iterate over all the values in its properties, whereas an Array will return the keys instead. Here's a link to a JSFiddle demonstrating the difference--notice that the first for each, which uses an array, returns the indexes, not the values; in contrast, the second for each returns the actual values at those keys.
I get that since javascript allows numeric keys for objects, the existence of array-like objects is therefore technically possible, but why did they ever become common?
Maybe the thought was that these array-like objects don't just have numeric keys, e.g. arguments has the callee property, so they can't be proper arrays to accommodate those properties.
But in javascript, it's perfectly valid to treat an array as an object and use non-numeric keys:
var myArguments = [];
myArguments[0] = 0;
myArguments['callee'] = function(){console.log('callee')};
If the object is array-like and would benefit from having access to the functions it would otherwise inherit from the array prototype, what would be advantage of making it an array-like object instead?
Edit: in case it wasn't clear in my question, an array like object would be something like the arguments object that has sequential numeric properties starting from zero, and has a length property that is one less than the highest numeric key. It also doesn't inherit from the array prototype, and doesn't provide access to array methods.
There is no big advantage, as you can access objects and arrays in very similar ways, array[number] for arrays, and object.propery, and object["property"] for objects. Arrays are better for storing data, not functions, in my opinion, and objects are better for storing sets of functions, in my opinion. For example, arrays could store your answers in a memory game, but an object would store the command for the game, like start or end.
I think the biggest advantage of using Array-Like object, is an object itself. An object has less overhead than an Array.
Can read: Array vs. Object efficiency in JavaScript
The other advantage of using objects, Language does not have to create/allocate contiguous memory as in Array. The object is more dynamic in nature. The array has to create a memory block in advance. and update on overload.
Read more: How are the JavaScript Arrays internally resizing?
Another factor, I think lookup in a map or object is faster.
Edit: As #Bergi stated, I forgot to add length property to the object. Also, I realized that my answer was not relevant. So I updated it after a short research.
In Typescript an arraylike object is defined like below:
interface ArrayLike<T> {
length: number;
[n: number]: T;
}
There are two main examples of array-like objects: arguments and HTMLCollection. The reason for using an array-like object is to use an array as only a data container without any behavior. As you could realize, if you try to use, say forEach, on arguments object you will get a type error since it's not defined on it. If you strictly believe that the array you are creating is only to be used as a data container without any methods whatsoever, then go with array-like objects. However, important to notice that they are getting scarcer day by day especially after ES6.
Actually Array in JS is an Object :)
As long as You need array, it is bad idea to create array-like objects, because JS engines optimize speed of arrays.
Yet, its possible.
I've looked around to see whether Javascript supports associative arrays and despite the fact that it clearly says that it doesn't, it seems to work anyway?
I'd love to know if anything has changed in the specifications and whether or not it's recommended to use them.
Sample code:
var foo = new Array;
foo["bar"] = "It works";
console.log(foo["bar"]);
You should use objects for that, they are first-class citizens in JavaScript:
var foo = {
"bar": "It works"
};
console.log(foo.bar);
console.log(foo["bar"]);
In Javascript, foo["bar"] is semantically equivalent to foo.bar. But this is Javascript object, not associative array. As you can see, however, you can treat the object as associative array.
I've looked around to see whether Javascript supports associative arrays and despite the fact that it clearly says that it doesn't
Where did you see that it clearly stated that JavaScript does not support associative arrays?
Associative arrays--a collection of key/value pairs (also called maps, dictionaries, and many other names in various contexts)--are the fundamental datatype in Javascript. However, in JavaScript, they are called "objects".
However, given your sample code:
var foo = new Array;
foo["bar"] = "It works";
it seems you may be asking a slightly different question, which is "Can a JavaScript array contain properties (other than its numerically indexed ones)"?
The answer, as well documented, and covered in countless question here on SO, is "yes". The reason is that in JavaScript, arrays are a special type of object, so like all objects, they can have named properties.
whether or not it's recommended to use them.
If you mean is it recommended to hang named properties off a JavaScript array, opinions differ. You can take a look at this question.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
What’s the difference between “Array()” and “[]” while declaring a JavaScript array?
What is the difference between these two methods of defining an array in javascript ?
var arrayList = []
and
var arrayListAgain = new Array();
One is good and the other is bad :-)
No seriously, the first way is shorter (fewer bytes sent over the wire) and it doesn't have any weird potential problems. The second one, however, will work fine.
The weird part with new Array() is this: if you pass one numeric parameter to the constructor, it means "initialize the array so that there are that there are the given number of empty (null) array elements, and so that length is equal to the given number." (Well it has to be an integer, I think actually.) If you pass a single non-number, or two or more numbers, it means, "initialize the array so that its contents reflect this argument list."
Ok now I said there was a weird part, and it's this: if you're using some sort of server side framework, and you want to create an array of numeric values (integer values), like say unique database keys, then you might be tempted to do this:
var keys = new Array(<# favoriteTemplateLanguage.forEach(idList): print(id + ',') #>);
(I made up that syntax of course.) Now what happens if there's just one "id" in your server-side list of keys?
You can use the second one to define an array of a predefined length, e.g.
var arrayListAgain = new Array(20);
will create an array with 20 (undefined) elements.
Also see new Array (len).
none what so ever. Both create a new instance of an Array object.
Douglas Crockford in 'Javascript the good parts' recommends the former method as it is more concise.
They are the same. According to http://www.hunlock.com/blogs/Mastering_Javascript_Arrays:
Current best-practice eschews the
"new" keyword on Javascript
primitives. If you want to create a
new Array simply use brackets [] like
this… var myArray = [];
I recommend reading that page, it contains a lot of useful information about arrays and JS in general.
My JavaScript code stores a lot of data in arrays. I want to retrieve a key using something similar to what I wrote below. It key that should be retrieved is based on variables that are page-dependent . The following code doesn't work. Can anyone give me a solution to this problem?
This is part of a script that does automatic conjugation. (looks for SUBJECT in a div and then looks for VERB in another div and then conjugates the verb by retrieving the conjugated form from the array)
function getarray(Array,Key) {
return Array[Key];
}
Example of how it should work:
verb = innerhtmlfromdiv;
subject = innerhtmlfromotherdiv;
function getarray(Array,Key) {
return Array[Key]; }
conjugatedverb = getarray(verb,subject);
htmltextbox.value = conjugatedverb;
First off, what you want is an Object, not an Array. I'm guessing that you're new to javascript and your previous language was either PHP or PERL, and so you think what you're using is an "Associative Array".
The basics: There is no such thing as Associative arrays in Javascript. There is Objects, and a non-primitive subclass of Object called Array, which has some methods for dealing with Numericly named object properties, and a magic length property.
Since the keys you are dealing with are strings, not numbers, you have no use for Arrays.
Javascript Objects on the other hand are similar to an Associative array in php, or a hash in perl. (but they are not exactly the same thing).
As you have no doubt discovered, with an Object, you can use subscript notation to access certain properties, as in
verbs["go"] = "went";
this is equivilent to
verbs.go = "went";
a common mistake is to think that the dot notation is only used for objects, and the subscript notation for "associative arrays", because this is how it works in PHP. In javascript the two notations are interchangable. Since Arrays are a subclass of Object, the above examples work on them as well (but they don't use any special properties of Arrays).
As for your specific problem:
You need an object full of objects.
so for instance
var verbs = {
"do":{"Truck":"Drive","Blender":"Turn On","Bike":"Ride"},
"take":{"Money":"Steal","Julie":"Accompany","Lever":"Pull}
}
then your function would be:
function conjugate (verb, subject) {
return verbs[verb][subject];
}
and an example of its use would be
conjugate("do","Truck") // returns "Drive"
Try changing the parameter name Array to something else. Array is the name of a built-in function/object in javascript.
I don't quite get the point of the function. This is like writing:
function getValue(var) {return var}
Why not just get the value the normal way without wrapping it in a useless function:
conjugatedverb = verb[subject];
htmltextbox.value = conjugatedverb;
Also, your code doesn't make sense when you claim to do an innerHTML from an element and somehow get an object instead of a string. What is really going on? I think your problem starts even before this snippet of code.