I recently found out that in the chrome console I was able to do something really unusual.
Here's a simple example using an array of objects.
g = [{age: 23}, {age:33}];
g.foo = "bar";
> (2) [{…}, {…}, foo: "bar"]
I think I'm able to do this because all js data structures are objects? Is there any way get access to foo:bar without knowing what it is beforehand?
g = g.filter(function(e){
return e.age !== 33;
});
> (2) [{…}]
Specifically I'm trying to filter an array, without losing the object attributes that I set like foo:"bar".
The filtered arrays I'm getting back do not contain the object attributes I had before.
So my question is what is the best way to get access to attributes that I set on an array object when I treat it like an object in this strange way?
Ideally I could run something(g) and get back {foo: 'bar'}, or a list of all the props that exist on this object that aren't related to the array aspect of it.
Or is this just a super hacky idea and I shouldn't do it like this in the first place?
Thanks!
You could use Object.keys for own enumerable keys of the object, even for arrays.
While own properties are possible, it is not advisable, because it could lead to lose some properties, if used with JSON.stringify more about disadvantage here: Is it good practice to add properties on array in javascript (still opinion-based).
var g = [{ age: 23 }, { age: 33 }];
g.foo = "bar";
console.log(Object.keys(g));
console.log(JSON.stringify(g));
This code get all enumeral keys in your object:
let g = [{age: 23}, {age:33}];
g.foo = "bar";
let keys = [];
for(var x in g){
keys.push(x);
}
console.log(keys)
But this code get all keys( from prototype also), best way for get keys -use Object.keys(g)
If you want get all keys without prototype : use Object.getOwnPropertyNames(g)
Related
This is more of a general question than a problem I need solved. I'm just a beginner trying to understand the proper way to do things.
What I want to know is whether or not I should only use objects as prototypes (if that's the correct term to use here) or whether or not it's OK to use them to store things.
As an example, in the test project I'm working on, I wanted to store some images for use later. What I currently have is something like:
var Images = {
james: "images/james.png",
karen: "images/karen.png",
mike: "images/mike.png"
};
Because I would know the position, I figure I could also put them in an array and reference the position in the array appropriately:
var images = ["images/james.png", "images/karen.png", "images/mike.png"];
images[0];
Using the object like this works perfectly fine but I'm wondering which is the more appropriate way to do this. Is it situational? Are there any performance reasons to do one over the other? Is there a more accepted way that, as a new programmer, I should get used to?
Thanks in advance for any advice.
Introduction
Unlike PHP, JavaScript does not have associative arrays. The two main data structures in this language are the array literal ([]) and the object literal ({}). Using one or another is not really a matter of style but a matter of need, so your question is relevant.
Let's make an objective comparison...
Array > Object
An array literal (which is indirectly an object) has much more methods than an object literal. Indeed, an object literal is a direct instance of Object and has only access to Object.prototype methods. An array literal is an instance of Array and has access, not only to Array.prototype methods, but also to Object.prototype ones (this is how the prototype chain is set in JavaScript).
let arr = ['Foo', 'Bar', 'Baz'];
let obj = {foo: 'Foo', bar: 'Bar', baz: 'Baz'};
console.log(arr.constructor.name);
console.log(arr.__proto__.__proto__.constructor.name);
console.log(obj.constructor.name);
In ES6, object literals are not iterable (according to the iterable protocol). But arrays are iterable. This means that you can use a for...of loop to traverse an array literal, but it will not work if you try to do so with an object literal (unless you define a [Symbol.iterator] property).
let arr = ['Foo', 'Bar', 'Baz'];
let obj = {foo: 'Foo', bar: 'Bar', baz: 'Baz'};
// OK
for (const item of arr) {
console.log(item);
}
// TypeError
for (const item of obj) {
console.log(item);
}
If you want to make an object literal iterable, you should define the iterator yourself. You could do this using a generator.
let obj = {foo: 'Foo', bar: 'Bar', baz: 'Baz'};
obj[Symbol.iterator] = function* () {
yield obj.foo;
yield obj.bar;
yield obj.baz;
};
// OK
for (const item of obj) {
console.log(item);
}
Array < Object
An object literal is better than an array if, for some reason, you need descriptive keys. In arrays, keys are just numbers, which is not ideal when you want to create an explicit data model.
// This is meaningful
let me = {
firstname: 'Baptiste',
lastname: 'Vannesson',
nickname: 'Bada',
username: 'Badacadabra'
};
console.log('First name:', me.firstname);
console.log('Last name:', me.lastname);
// This is ambiguous
/*
let me = ['Baptiste', 'Vannesson', 'Bada', 'Badacadabra'];
console.log('First name:', me[0]);
console.log('Last name:', me[1]);
*/
An object literal is extremely polyvalent, an array is not. Object literals make it possible to create "idiomatic" classes, namespaces, modules and much more...
let obj = {
attribute: 'Foo',
method() {
return 'Bar';
},
[1 + 2]: 'Baz'
};
console.log(obj.attribute, obj.method(), obj[3]);
Array = Object
Array literals and object literals are not enemies. In fact, they are good friends if you use them together. The JSON format makes intensive use of this powerful friendship:
let people = [
{
"firstname": "Foo",
"lastname": "Bar",
"nicknames": ["foobar", "barfoo"]
},
{
"firstName": "Baz",
"lastname": "Quux",
"nicknames": ["bazquux", "quuxbaz"]
}
];
console.log(people[0].firstname);
console.log(people[0].lastname);
console.log(people[1].nicknames[0]);
In JavaScript, there is a hybrid data structure called array-like object that is extensively used, even though you are not necessarily aware of that. For instance, the good old arguments object within a function is an array-like object. DOM methods like getElementsByClassName() return array-like objects too. As you may imagine, an array-like object is basically a special object literal that behaves like an array literal:
let arrayLikeObject = {
0: 'Foo',
1: 'Bar',
2: 'Baz',
length: 3
};
// At this level we see no difference...
for (let i = 0; i < arrayLikeObject.length; i++) {
console.log(arrayLikeObject[i]);
}
Conclusion
Array literals and object literals have their own strengths and weaknesses, but with all the information provided here, I think you can now make the right decision.
Finally, I suggest you to try the new data structures introduced by ES6: Map, Set, WeakMap, WeakSet. They offer lots of cool features, but detailing them here would bring us too far...
Actually, the way you declared things brings up the "difference between associative arrays and arrays".
An associative array, in JS, is really similar to an object (because it's one):
When you write var a = {x:0, y:1, z:3} you can access x using a.x(object) or a["x"](associative array).
On the other hand, regular arrays can be perceived as associative arrays that use unsigned integers as ID for their indexes.
Therefore, to answer your question, which one should we pick ?
It depends : I would use object whenever I need to put names/labels on thing (typically not for a collection of variables for instance). If the type of the things you want to store is homogeneous you will probably use an array (but you can still go for an object if you really want to), if some of/all your things have a different type than you should go for an object (but in theory you could still go for an array).
Let's see this :
var a = {
x:0,
y:0,
z:0
}
Both x,y,z have a different meaning (components of a point) therefore an object is better (in terms of semantic) to implement a point.
Because var a = [0,0,0] is less meaningful than an object, we will not go for an array in this situation.
var storage = {
one:"someurl",
two:"someurl2",
three:"someurl3",
}
Is correct but we don't need an explicit name for every item, therefore we might choose var storage = ["someurl","someurl2","someurl3"]
Last but not least, the "difficult" choice :
var images = {
cathy: "img/cathy",
bob: "img/bob",
randompelo: "img/randompelo"
}
and
var images = ["img/cathy","img/bob","img/randompelo"]
are correct but the choice is hard. Therefore the question to ask is : "Do we need a meaningful ID ?".
Let's say we work with a database, a meaningful id would be better to avoid dozens of loops each time you wanna do something, on the other hand if it's just a list without any importance (index is not important, ex: create an image for each element of array) maybe we could try and go for an array.
The question to ask when you hesitate between array and object is : Are keys/IDs important in terms of meaning ?
If they are then go for an object, if they're not go for an array.
You're correct that it would be situational, but in general its not a good idea to limit your program by only allowing a finite set of supported options like:
var Images = {
james: "images/james.png",
karen: "images/karen.png",
mike: "images/mike.png"
};
Unless, of course, you happen to know that these will be the only cases which are possible - and you actively do not want to support other cases.
Assuming that you dont want to limit the possibilities, then your array approach would be just fine - although personally I might go with an array of objects with identifiers, so that you arent forced to track the index elsewhere.
Something like:
var userProfiles = [
{"username": "james", "image": "images/james.png"},
{"username": "karen", "image": "images/karen.png"},
{"username": "mike", "image": "images/mike.png"}
];
If you have an array of objects like
[{rID:53, name:Roger, age:43},{rID:12, name:Phil, age:22}]
is it possible instead to give each a object a key like
[53:{name:Roger, age:43},12:{name:Phil, age:22}]
?
I understand that each object has an index number, but I'm looking for a way to find objects not based on their index pos, and preferably without having to loop through until you find an object with rID=53 type thing.
I'd be using PKs from mysql rows to give each object it's key.
Cheers
If you want an unordered collection of variables with arbitrary keys. Then use an object.
{"53":{name:Roger, age:43},"12":{name:Phil, age:22}}
Arrays can have only numeric keys, but if you want to assign a value to an arbitrary position, you have to do so after creating the array.
var some_array = [];
some_array[53] = {name:Roger, age:43};
some_array[22] = {name:Phil, age:22};
Note that this will set the array length to 54.
Note that in both cases, you can't have multiple values for a given property (although you could have an array of values there).
You need an object for that.
{
53: {
name: "Roger",
age: 43
},
12: {
name: "Phil",
age: 22
}
}
No. You cannot have a key and an index in a js array. Arrays only have indices, Objects only have keys. There is no such thing like a associative array in JavaScript. If the order (of your original array) does not matter, you can use an object though:
{53:{name:"Roger", age:43},12:{name:"Phil", age:22}}
You can use objects to do this
var map = {"53":{"name": "Roger", "age": "43"},"12":{"name": "Phil", "age": "22"}};
Then access the value like an array (note, i'm using string because that's what keys are stored as, strings, you can access it using an integer, but it will just be converted to a string when searching for the property anyway):
map["53"]
You can also loop through this map object:
for (var key in map) {
var value = map[key];
}
I'm learning js, find this code:
var arr = [
{id: 111, now: '12.02.2014'}
];
What is this? I know that var arr = [ ... ] - array, but what is {} in array and how i can work with this data and display this ?
{} is the syntax for creating an object. It's called an object initializer, but it's frequently called an "object literal".
So what you're doing there is creating an object which has id and now properties, and putting that object into an array as its only entry.
...how i can work with this data and display this ?
To display the id, for instance:
console.log(arr[0].id);
What that does:
arr[0] - retrieve the first entry in the array. In our case, it's an object.
.id - Get the value of the id property from that object.
We could also write it like this:
var obj = arr[0];
console.log(obj.id);
Alternately, if we didn't know in advance what property we wanted but we were given a string containing the name of the property, we could use [] with the object as well:
var nameOfProperty = "id";
var obj = arr[0];
console.log(obj[nameOfProperty]);
JavaScript has both the dotted syntax (obj.id), and the bracketed syntax (obj["id"]) for accessing object properties, where with the latter you can use any string (including one from a variable).
Yes, that is an object inside an array. In truth, all values, from numbers to functions to arrays, are actually objects.
You can access this object in the same way as you would any item of an array. (arr[0])
You can then access properties of the object, for example arr[0].id.
For more about objects, take a look at Objects on MDN.
I want to create a nested array in Javascript but can't do the thing what I want, I don't know if it is even possible. Here is an example of what kind of array I want to create:
var array = ['id1', 'id2', 'id3', 'id4'];
Then I want to add new array for each id such way that id values stayed the same. Why? because I want to use indexOf method to find out the element index of main array with sub array id. Something like this:
array[0]['par1'] should return the value of parameter1
array[0]['par2'] should return the value of parameter2
...
array[0] should return "id1" because
alert(array.indexOf("id1")) must return 0 ;
If there is some way of doing it, that would be great to know, but if it is not than I think I will use 2 arrays, one will hold sub arrays and another the ids
sorry for my bad English, I tried my best to explain my needs.
Maybe you want to do
array[0] = {par1: 'somevalue', par2: someother};
array[1] = {par1: 'anotehrone', par2: stillanother};
This sets as elements of you array javascript objects, here used as associative arrays. They enable you to set or get elements by key :
array[0]['par1'] = 'new value'; // write
var newval = array[0]['par1']; // read
But if you also want to have array[0] returning something that's not a generic object but a string... then you probably don't want javascript. This language just doesn't work like that.
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.