Does Javascript have associative arrays? - javascript

Does Javascript have associative arrays? Please explain.

Nope; JavaScript arrays are just numeric keys and mixed values. The same thing can be achieved (or, actually, it's exactly the same as associative arrays in other languages) with objects:
var foo = {
a: 123,
b: 'CDE'
};
foo.a; // 123
foo['a']; // 123
You could use arrays:
var foo = [];
foo.a = 123;
foo.b = 'CDE';
foo.b; // CDE
foo['b']; // CDE
HOWEVER, this should never be done because this will not enter the key/value pairs into the array, but add them to the array object as properties. (besides, {a: 123} is easier than a = []; a.a = 123) If you need key/value pairs, use Objects. If you need an enumerated list, use arrays.

This answer is pretty much a copy-paste of my previous answer on this question.
The situation has changed in the five years since this question was asked.
Due to weak typing associative arrays can be faked in JavaScript:
>> var names = new Array();
undefined
>> names["first"] = "Dotan";
"Dotan"
>> names["last"] = "Cohen";
"Cohen"
>> for ( key in names ) { console.log(key+" "+names[key]) }
undefined
first Dotan
last Cohen
That is sometimes useful, and all browsers released since 2012 support it, but there are caveats! The array cannot be simply read back:
>> names
Array [ ]
More importantly, the array's length cannot be easily retrieved:
>> names.length
0
Therefore this is not an associative array in the sense that JavaScript would have supported it had it been intended, but rather a workaround that is often useful if for whatever reason a real JS object does not support what you need:
>> var names = {};
undefined
>> names.first = "Dotan";
"Dotan"
>> names.last = "Cohen";
"Cohen"
>> for ( key in names ) { console.log(key+" "+names[key]) }
undefined
first Dotan
last Cohen
>> names
Object { first: "Dotan", last: "Cohen" }
>> Object.keys(names).length
2

The closest we have is an object; the easiest way you can define this is using object literal syntax.
var assocArray = {
key: 1,
key2: 2
};
You should be wary of a few things however:
It does not have a .length property.
You should use for in to iterative over it, rather than for(;;;);, but should combine it with hasOwnProperty():
for (var x in assocArray) {
if (assocArray.hasOwnProperty(x)) {
// x = the key, assocArray[x] = the value
}
}
There is no concept of ordering/ sorting the members. Whilst all implementations I know of iterate the members in the order they were added, this is not standardised.

Instead of associative arrays. Javascript has objects. Properties of an object are addressed using a string.
var obj1 = {}; // declare empty object
var obj2 = {a: 1, b: 'string', c: [4,5]}; // obj with 3 properties, a, b, and c
// note that the 'c' property contains an anonymous array
alert(obj2.a); // shows 1
obj2.a = 'another string'; // redefine the 'a' property
obj2.cookie = 'oatmeal'; // add a new property to the object
obj2['ice_cream'] = {vendor: 'Beyers',
flavor: 'Chocolate Surprise'}; // add anonymous object as
// a new property for the object
assert(obj2.a === obj2['a']); // two ways to retrieve the value
var i = 'a'; // using an index varable
assert(obj2.a === obj2[i]); // note the i does not have apostrophes around it
See the Quirksmode docs

Something comparable in JavaScript is an object.
var my_obj = { key : 'value' }

Sure it does (kind of, use objects)
var foo = {
bar: "hello"
}
accessible with
foo.bar

Related

Index a JS object like a Metatable in Lua

Is there a way to index an object in JavaScript like a Metatable in Lua?
Like for example:
var obj = {a:"a",b:"b",properties:{c:"c",d:"d"}}
metatable(obj,obj.properties) // Make it so that if you try to index something that's not inside the object it will go to the parameter one
console.log(obj.a) // "a"
console.log(obj.c) // "c"
To LMD:
How do I do it for multiple objects? Like for example:
var objs = [
obj1 = {name:"Button";class:"button";properties:{text:"Press this"}]
]
for (i in objs){
metatable(objs[i],objs[i].properties)
}
console.log(objs.obj1.text) // "Press this"
Yes: JavaScript has prototypes. These aren't exactly the same as Lua but can be used for simple metatable indexing purposes. One way to achieve your example would be as follows:
const properties = {c: "c", d: "d"} // prototype
const obj = Object.create(properties) // create object with prototype
obj.a = "a"; obj.b = "b";
console.log(obj.a) // "a"
console.log(obj.c) // "c"
Or if you already have the objects given, as in your second example, you may want to use Object.setPrototypeOf(object, prototype), which is comparable to setmetatable(object, {__index = prototype}) in Lua:
const objs = [{name:"Button", class:"button", properties: {text:"Press this"}}]
for (const obj of objs) Object.setPrototypeOf(obj, obj.properties)
console.log(objs[0].text) // "Press this"
that is, the metatable function you've been searching for literally is Object.setPrototypeOf!

C structure to JSON

I am very new to JS, have been working in C/C++ before,
I need an equivalent of below C structure in JSON
struct tmp_t{
int a;
char c_str[1024];
};
struct tmp2_t{
int a2;
.
.
char c2_str[1024];
};
struct my {
int number;
struct tmp_t tmp[100];
struct tmp2_t tmp2[100][1000];
};
For a json like
var myJSON = {
"number":0,
.
.
};
I need to access it like
myJSON.tmp[0].a = 10;
myJSON.tmp2[0][1].c2_str = "hello world"
any input is highly appreciated
Javascript properties are not typed like they are in C so there is no purely "equivalent" expression in javascript. You don't predeclare typed data structures like your C code has. I given variable or property in javascript can be assigned any value or reference - there is not hard typing. So without variables that can only contain a specific type like C has, there's no pre-declaring of data structure definitions like you have included from C.
Instead, you just declare the properties you want to use on a live object or if you intend to use many of them, you can create a prototype which you can instantiate when needed.
A direct declaration of a live object instance somewhat like your last structure would look like this:
var my = {
number: 10,
tmp: new Array(100),
tmp2: new Array(100)
};
This would declare an object named my that had three properties called number, tmp and tmp2. number initially contained the number 10 and the other two properties contained arrays of length 100 who's values were undefined. I don't know of any compact way to predefine your two dimensional array in javascript without running code in a loop to initialize it.
This data defintion would let you access my.number, my.tmp and so on.
If you want your arrays to contains objects with properties themselves, then you need to populate those arrays with the objects.
var my = {
number: 10,
tmp: [{a: 1, c_str: "foo"}, {a: 2, c_str: "whatever"}],
tmp2: new Array(100)
};
Or, in code, you could add in item to the tmp array with code like this:
var my = {
number: 10,
tmp: [],
tmp2: []
};
my.tmp.push({a: 1, c_str: "foo"});
my.tmp.push({a: 2, c_str: "whatever"});
Or, you could create the object separately and then put it in the array:
var obj = {}; // new empty object
obj.a = 1; // assign property
obj.c_str = "foo"; // assign property
my.tmp.push(obj); // put object into the array
obj = {}; // new empty bject
obj.a = 2;
obj.c_str = "whatever";
my.tmp.push(obj);
Or, you could assign each property individually like this:
my.tmp.push({}); // put empty object into the array
my.tmp[0].a = 1; // assign property to the object
my.tmp[0].c_str = "foo"; // assign property to the object
my.tmp.push({});
my.tmp[1].a = 2;
my.tmp[1].c_str = "whatever";
In either case, you could then access the data like this:
console.log(my.tmp[0].a); // 1
console.log(my.tmp[0].c_str); // "foo"

javascript returning difference between two objects

I have an object that looks like this:
var MyObject = {
prop1 = 12345,
prop2 = "string1",
ListOfOtherObject = an array of another type of object,
ListOfAnotherObject = an array of objects}
Let's say I have two objects: Object1 and Object2. Object2 was initially a deep-copy of Object1 and it was modified through the user's interactions with the UI. I'm looking to get the difference between both objects, especially when it comes to the arrays.
For instance, ListOfOtherObject in Object2 might contain a modified version of some objects as well as new objects.
I'm thinking about looping through each array and then looping through each object within but there might be some more efficient way to do it, especially with jquery. Or may be going with JSON.stringify and compares strings and retuns some sort of string difference. I was wondering if anyone had any suggestions on how to do this.
Thanks.
You need to specify what your comparison needs to do. For example, given:
var o = {name: 'fred'};
var p = {name: 'fred'};
var a = {o:o};
var b = {o:o};
then:
a == b; // false, a and b are different objects
a.o == b.o; // true since a.o and b.o reference the same object
but if comparing objects:
b.o = p;
a.o == b.o; // false since a.o and b.o reference different objects
or if comparing primitives:
a.o.name == b.o.name; // true since the value of both expressions is the string 'fred'
// even though a.o and b.o are different objects
Does Type or constructor matter? What about:
b.o = [];
b.o.name = 'fred';
a.o.name == b.o.name; // true or false? a.o is an object, b.o is an array

JS & jQuery: inArray() and indexOf() are not working properly if indexes are strings?

I have an array like this:
var arr = [];
arr['A string'] = '123';
arr['Another string'] = '456';
and Im trying to find an index of '123' or '456'.
Both:
var string = $.inArray('123', arr)
and
var string = arr.indexOf('123')
are giving me -1. Is it possible to get it working when indexes are strings?
Like all Array methods and the length property, the indexOf method of an Array object only considers numeric properties of the Array. These are properties whose names are unsigned integers. To test for the existence of a property with a particular value, you can do something like this on any object, including arrays. There's no guarantee about the enumeration order of property names, so if there's more than one property with a particular value then you can't be sure which property you'll get:
function findPropertyWithValue(obj, val) {
for (var i in obj) {
if (obj.hasOwnProperty(i) && obj[i] === val) {
return i;
}
}
return null;
}
var arr = [];
arr['A string'] = '123';
arr['Another string'] = '456';
alert(findPropertyWithValue(arr, "123")); // 'A string'
Note that since all property names, including numeric ones, are converted into strings, you can assign array properties using strings:
var arr = [];
arr["1"] = "foo";
arr[3] = "bar"
arr.indexOf("foo"); // 1
arr.indexOf("bar"); // 3
The problem is that you are using a JavaScript array as an associative array, something that it is not. The indices of a JavaScript array are unsigned 32 bit integers and therefore you can't use *strings**. You would either use an array like so
// I'm guessing that you meant to give numerical and not string values
var arr = [123, 456];
or use an object
var obj = {
'A string' : 123,
'Another string' : 456
};
Note that using an object, 'A string' and 'Another string' are properties of object obj and can't be indexed like the values in an array. You can check that an object has a property a number of ways, one of which would be using hasOwnProperty
if (obj.hasOwnProperty('A string')) {
// if obj has property 'A string' as a direct property
}
another would be using the in keyword
if ('A string' in obj) {
// if obj has a property 'A string' as a property (could be an inherited property too)
}
**unless the string is the string representation of a 32 bit unsigned integer as Tim points out, but I think it's fair to say that a lot of JavaScript developers would say stick to using integers for clarity.*

How to access the properties of a JavaScript object?

while review a javascript coding, i saw that
var detailInf = {
"hTitle":"Results",
"hMark":"98"
};
What's the concept behind this js coding. While give alert for the variable its shows as "[object Object]". So this is an object, then how can we access the variable and reveal the data from this object.
Try doing this:
alert(detailInf['hTitle']);
alert(detailInf.hTitle);
Both will alert "Results" - this is a Javascript object that can be used as a dictionary of sorts.
Required reading: Objects as associative arrays
As a footnote, you should really get Firebug when messing around with Javascript. You could then just console.log(detailInf); and you would get a nicely mapped out display of the object in the console.
That form of a JavaScript object is called an object literal, just like there are array literals. For example, the following two array declarations are identical:
var a = [1, 2, 3]; // array literal
var b = new Array(1, 2, 3); // using the Array constructor
Just as above, an object may be declared in multiple ways. One of them is object literal in which you declare the properties along with the object:
var o = {property: "value"}; // object literal
Is equivalent to:
var o = new Object; // using the Object constructor
o.property = "value";
Objects may also be created from constructor functions. Like so:
var Foo = function() {
this.property = "value";
};
var o = new Foo;
Adding methods
As I said in a comment a few moments ago, this form of declaring a JavaScript object is not a JSON format. JSON is a data format and does not allow functions as values. That means the following is a valid JavaScript object literal, but not a valid JSON format:
var user = {
age : 16,
// this is a method
isAdult : function() {
// the object is referenced by the special variable: this
return this.age >= 18;
}
};
Also, the name of the properties need not be enclosed inside quotes. This is however required in JSON. In JavaScript we enclose them in brackets where the property name is a reserved word, like class, while and others. So the following are also equivalent:
var o = {
property : "value",
};
var o = {
"property" : "value",
};
Further more, the keys may also be numbers:
var a = {
0 : "foo",
1 : "bar",
2 : "abz"
};
alert(a[1]); // bar
Array-like objects
Now, if the above object would have also a length property, it will be an array like object:
var arrayLike = {
0 : "foo",
1 : "bar",
2 : "baz",
length : 3
};
Array-like means it can be easily iterated with normal iteration constructs (for, while). However, you cannot apply array methods on it. Like array.slice(). But this is another topic.
Square Bracket Notation
As Paolo Bergantino already said, you may access an object's properties using both the dot notation, as well as the square bracket notation. For example:
var o = {
property : "value"
};
o.property;
o["property"];
When would you want to use one over the other? People use square bracket notation when the property names is dynamically determined, like so:
var getProperty = function(object, property) {
return object[property];
};
Or when the property name is a JavaScript reserved word, for example while.
object["while"];
object.while; // error
That's an object in JSON format. That's a javascript object literal. Basically, the bits to the left of the :'s are the property names, and the bits to the right are the property values. So, what you have there is a variable called detailInf, that has two properties, hTitle and hMark. hTitle's value is Results, hMark's value is 98.
var detailInf = { "hTitle":"Results", "hMark":"98"};
alert(detailInf.hTitle); //should alert "Results"
alert(detailInf.hMark); //should alert "98
Edit Paolo's answer is better :-)
As Dan F says, that is an object in JSON format. To loop through all the properties of an object you can do:
for (var i in foo) {
alert('foo[' + i + ']: ' + foo[i]);
}

Categories

Resources