I have a js object that looks like this:
var object = {
"divisions": {
"ocd-division/country:us": {
"name": "United States",
}
}
};
I want to access the property listed under the nested object "ocd-division/country:us" (aka "name"), but the problem I'm having is that "ocd-division/country" is a variable object. Like it might be ":can" for Canada or something.
My question is, can I still access the name property under that object even though it's variable? I wrote the code I came up with below, but it calls the object literally, so it can't account for a change in the object's name.
var country = document.getElementById("p");
p.innerHTML = object.divisions["ocd-division/country:us"].name;
I'm new to JavaScript so I'm sorry if this is a dumb question.
When you don't know the properties of an object, you can use
for...in loop
It iterates enumerable own and enumerable inherited properties.
Object.keys
It returns an array which contains enumerable own properties.
Object.getOwnPropertyNames
It returns an array which contains own properties.
// Adding properties: "ownEnumerable", "ownNonEnumerable",
// "inheritedEnumerable" and "inheritedNonEnumerable"
var obj = Object.defineProperties({}, {
ownEnumerable: {enumerable: true},
ownNonEnumerable: {},
});
Object.defineProperties(Object.prototype, {
inheritedEnumerable: {enumerable: true},
inheritedNonEnumerable: {},
});
// Display results
function log(id, arr) {
document.getElementById(id).textContent = '[' + arr.join(', ') + ']';
}
log('forin', function(forInProps){
for (var prop in obj) forInProps.push(prop);
return forInProps;
}([]));
log('keys', Object.keys(obj));
log('names', Object.getOwnPropertyNames(obj));
<dl>
<dt><code>for...in</code></dt><dd id="forin"></dd>
<dt><code>Object.keys</code></dt><dd id="keys"></dd>
<dt><code>Object.getOwnPropertyNames</code></dt><dd id="names"></dd>
</dl>
object.divisions[Object.keys(object.divisions)[0]].name
Sure...
for (var division in object.divisions) {
var name = object.divisions[division].name;
// Do what you want with name here
}
If the object has prototype methods you will want to use Object.prototype.hasOwnProperty() to ensure they don't get iterated like so:
for (var division in object.divisions) {
if (!object.divisions.hasOwnProperty(division)) continue;
var name = object.divisions[division].name;
// Do what you want with name here
}
Or use Object.keys() if you don't care about IE8 support and iterate over those.
Object.keys(object.divisions).forEach(function(division) {
var name = object.divisions[division].name;
// Do what you want with name here
});
EDIT: Upon re-reading your question it occurs to me that you may already know the key name but want to access the object with a variable key name, which is also absolutely fine:
var division = 'ocd-division/country:us';
object.divisions[division].name;
When using [] bracket notation to access an object you can insert any code that evaluates to a string, you could even call a function in there that returns a string.
See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors
You can iterate through object using for loop.
var obj = {
"divisions":{
"ocd-division/country:us":{
"name" : "United States"
}
}
}
Here is the for loop
for(var a in obj){ //loop first the object
for(var b in obj[a]){ // then second object (divisions)
for(var c in obj[a][b]){ //then third object (ocd-division/country:us)
if(c == 'name'){ //c is the key of the object which is name
console.log(obj[a][b][c]); //print in console the value of name which is United States.
obj[a][b][c] = "Canada"; //replace the value of name.
var objName = obj[a][b][c]; //or pass it on variable.
}
}
}
}
console.log(obj); //name: Canada
console.log(objName); //name: United States
You can also use this reference:
https://developer.mozilla.org/enUS/docs/Web/JavaScript/Reference/Statements/for
http://stackoverflow.com/questions/8312459/iterate-through-object-properties
Related
How can I loop through the array below and get the values of "car1"? The code below returns undefined
<script>
var myObj = {
"cars": {
"car1":"Ford",
"car2":"BMW",
"car3":"Fiat"
},
"cars2": {
"car1":"Ford2",
"car2":"BMW2",
"car3":"Fiat2"
}
}
for (x in myObj) {
alert(x.car1);
}
</script>
in your loop:
for (x in myObj) {
alert(x.car1);
}
x is the string value of key of your object. In order to get the car1 property of your nested object you can change your loop as:
for (x in myObj) {
alert(myObj[x].car1);
}
It is also a good practice to use hasOwnProperty while using for-in loop it might also iterate over properties which are in your object's prototype chain.
for (x in myObj) {
if (myObj.hasOwnProperty(x)) {
alert(myObj[x].car1);
}
}
For aggregating those values into an array, for example:
let aggregated = [];
var myObj = {
"cars": {
"car1":"Ford",
"car2":"BMW",
"car3":"Fiat"
},
"cars2": {
"car1":"Ford2",
"car2":"BMW2",
"car3":"Fiat2"
}
}
Object.keys(myObj).forEach(e => {
aggregated.push(myObj[e].car1)
})
console.log(aggregated)
If you have any other object inside and you want to get access to their properties too, you can create nested loop, like this:
var myObj = {
"cars": {
"car1":"Ford",
"car2":"BMW",
"car3":"Fiat"
},
"cars2": {
"car1":"Ford2",
"car2":"BMW2",
"car3":"Fiat2"
}
}
// Iterate over the first level
for (x in myObj) {
// Iterate over the second level
for (y in myObj[x]) {
document.getElementById("demo").innerHTML += myObj[x][y] + "<br>";
}
}
<div id="demo"></div>
This way you will be able to iterate through myObj[cars] and myObj[cars2] object properties too.
Your car1 property isn't at the level that you're trying to access it at. Loop through the object and check to see if car1 exists on the next level down. If it does, show the alert. Also note, you should have an if statement in your for in loop to make sure the property exists (or some other condition)
var myObj = {
"cars": {
"car1":"Ford",
"car2":"BMW",
"car3":"Fiat"
},
"cars2": {
"car1":"Ford2",
"car2":"BMW2",
"car3":"Fiat2"
}
}
for (var x in myObj) {
if (myObj.hasOwnProperty(x)) {
var obj = myObj[x];
if (obj.hasOwnProperty('car1')) {
alert(obj.car1);
}
}
}
<script>
var myObj = {
"cars": {
"car1": "Ford",
"car2": "BMW",
"car3": "Fiat"
},
"cars2": {
"car1": "Ford2",
"car2": "BMW2",
"car3": "Fiat2"
}
}
var res = Object.values(myObj)
.map(i => i.car1)
.filter(name => (name !== 'Ford2'));
document.getElementById("demo").innerHTML = res;
You should just change the for loop to
for (x in myObj) alert(myObj[x].car1);
Try it out
You have a small misgiving here. You're not looping over an Array, you are looping over the properties of an Object with a for...in loop.
You should be careful with that. You probably want to make it 'safe'(won't traverse the prototype or non enumerable properties) by changing to a more updated methods of traversal. Namely safely getting the values of the object, not the keys and then looping over it with some of the newer looping functions.
We'll be using Object.values to get an array of the values since we don't need the keys, then Array.prototype.filter() to filter out anything without a 'car1' property as reported by Object.prototype.hasownproperty(), and finally mapping over it to transform it with Array.prototype.map(). As a way to keep the alerts in, we will then be alerting on each of them using Array.prototype.forEach()
Object
.values(myObj) // since we don't care about the keys, only loop over the values
.filter(obj => // filter out any values without a 'car1' property
obj.hasOwnProperty('car1')
)
.map(obj => obj.car1) // de-nest the car1 property
.forEach(alert)
Now we have an array of the car1 properties of the values in the Object. The good news is this will work if given an Array of objects as well instead of a nested Object, but only because we don't care about the keys that hold the objects and only that an object actually has a 'car1' property
Tricks used for brevity
Arrow Functions
function (a,b){ return console.log(a,b) }
can be rewritten as
(a,b) => console.log(a,b)
Direct function reference
[1,2,3].forEach(item => alert(item))
can be rewritten since in JavaScript functions are first order and can be passed as arguments to other functions
[1,2,3].forEach(alert)
I'm making a dictionary of words, so there are 1,000,000+ words.
The problem comes when I need to store the word constructor. I know this is a reserved word in javascript, but I need to add it to the dictionary.
var dictionary = {}
console.log(dictionary ['word_1'])
//undefined, this is good
console.log(dictionary ['word_2'])
//undefined, this is good
console.log(dictionary ['constructor'])
//[Function: Object]
// this cause initialization code to break
How can I fix this? I could muck with the it like key=key+"_" but that seems bad. Is there anything else I can do?
Instead of using a JS object, you could use the built-in Map type which uses strings/symbols as keys and does not conflict with any existing properties.
Replace
var dictionary = {} with var dictionary = new Map()
Override the constructor key as undefined
According to the MDN Object.prototype page, the only thing that isn't hidden by the __fieldname__ schema is the "constructor field". Thus, you could just initialize your objects via { 'constructor': undefined }.
However, you would have to make sure that in your for .. in statements would filter out all keys with undefined as their value, as it would pick up constructor as a "valid" key (even though it wouldn't before you specifically set it to undefined). I.E.
for(var key in obj) if(obj[key] !== undefined) { /* do things */ }
Check for types when getting/setting
Otherwise, you could just check the type when you 'fetch' or 'store' it. I.E.
function get(obj, key) {
if(typeof obj[key] !== 'function') // optionally, `&& typeof obj[key] !== 'object')`
return obj[key];
else
return undefined;
}
I think you should store all words and translation of them in an array. When you need to translate a word, you can use find method of Array.
For example:
var dict = [
{ word: "abc", translated: "xyz" },
...
];
Then:
var searching_word = "abc";
var translation = dict.find(function (item) {
return item.word == searching_word;
});
console.log(translation.translated);
// --> xyz
To achieve expected result , use below option of using index to get value of any key value
var dictionary = {};
var dictionary1 = {
constructor: "test"
};
//simple function to get key value using index
function getVal(obj, val) {
var keys = Object.keys(obj);
var index = keys.indexOf(val);//get index of key, in our case -contructor
return obj[keys[index]]; // return value using indec of that key
}
console.log(getVal(dictionary, "constructor"));//undefined as expected
console.log(getVal(dictionary1, "constructor"));//test
console.log(dictionary["word_1"]);
//undefined, this is good
console.log(dictionary["word_2"]);
//undefined, this is good
codepen - https://codepen.io/nagasai/pen/LOEGxM
For testing , I gave one object with key-constructor and other object without constructor.
Basically I am getting the index of key first and getting value using index
I have an array of objects like so
myobj= [{"item1" : info in here},{"item2" : info in here}, {"item3" : info in here}]
I'm trying to modify one, but I only know its key. I need to pinpoint the item1 object so I can change its value (the values are random and I don't know them, so I can't rely upon them).
If I could just get the index of the item it would be pretty easy: myobj[index].value = "newvalue".
Maybe using the index isn't the best way, so if it isn't, I'm open to other ideas.
I was thinking I could try something like
myobj.objectVar
Where objectVar is the key I'm being passed (item1, for example), however this does not work, possibly because it's a variable? Is it possible to use a variable like this maybe?
If it helps, I'm using underscore.js as well.
Your guess at a solution doesn't work because you're not accessing the individual objects, you're accessing an array of objects, each of which has a single property.
To use the data in the format you've got now, you need to iterate over the outer array until you find the object that contains the key you're after, and then modify its value.
myobj= [{"item1" : info in here},{"item2" : info in here}, {"item3" : info in here}]
function setByKey(key, value) {
myObj.forEach(function (obj) {
// only works if your object's values are truthy
if (obj[key]) {
obj[key] = value;
}
});
}
setByKey('item1', 'new value');
Of course, the far better solution is to stop using an array of single-property objects, and just use one object with multiple properties:
myobj= {"item1" : info in here, "item2" : info in here, "item3" : info in here};
Now, you can simply use myObject.item1 = "some new value" and it will work fine.
You can write a function like,
function getElementsHavingKey(key) {
var objectsHavingGivenKey = [];
//loop through all the objects in the array 'myobj'
myobj.forEach(function(individualObject) {
//you can use 'hasOwnProperty' method to find whether the provided key
// is present in the object or not
if(individualObject.hasOwnProperty(key)) {
// if the key is present, store the object having the key
// into the array (many objects may have same key in it)
objectsHavingGivenKey.push(individualObject);
}
});
// return the array containing the objects having the keys
return objectsHavingGivenKey;
}
If you only want to get the index of elements having the given key
You can do something like this,
function getIndexesOfElementsHavingKey(key) {
var objectsHavingGivenKey = [];
//loop through all the objects in the array 'myobj'
myobj.forEach(function(individualObject, index) {
//you can use 'hasOwnProperty' method to find whether the provided key
// is present in the object or not
if(individualObject.hasOwnProperty(key)) {
//push index of element which has the key
objectsHavingGivenKey.push(index);
}
});
// returns the array of element indexes which has the key
return objectsHavingGivenKey;
}
Try this code:
function changeObj( obj, key, newval )
{
for( var i=0, l=obj.length; i<j; i++)
{
if( key in obj[i] )
{
obj[i] = newval;
return;
}
}
}
var myObjArray= [{"item1" : "info in here"},{"item2" : "info in here"}, {"item3" : "info in here"}]
To find and add new value to the object inside an array:
myObjArray.forEach(function(obj) {
for(var key in obj) {
// in case you're matching key & value
if(key === "item1") {
obj[key] = "update value";
// you can even set new property as well
obj.newkey = "New value";
}
}
});
You can access objects the same using their index, even the object inside the original object.
Is this kind of what your looking for:
var otherObj = [{"oitem":"oValue"}];
var myobj= [{"item1" : otherObj},{"item2" : "2"}, {"item3" : "tesT"}];
myobj[0].item1[0].oitem = "newvalue";
alert(myobj[0].item1[0].oitem);
So, I want to create an object (semi-automatically) using Jquery.
Instead of posting all of my code here, I'll give an example of what I want to do:
var myobject = {
'name1': {
'coord1':true,
'coord2':false,
'coord3':false,
},
'name2': {
'coord4':true,
'coord5':false,
'coord6':false,
}
}
1) I first want to check if 'nameX' is already in my object, if so, continue to step 2, if not, I want to add the name, and coordX with value true or false.
2) If 'nameX' is in the array, I want to check i 'coordX' is in the array. If so, I need to check if the corresponding value (true or false) is the same, and if not, replace it. If 'CoordX' is not in the object, I want to add it with the corresponding value.
For example:
var mynewname = 'name3';
var mynewcoord = 'coord5';
var mynewvalue = 'true';
var mynewname2 = 'name1';
var mynewcoord2 = 'coord4';
var mynewvalue = 'false';
When checking these values with the object this should give:
var myobject = {
'name1': {'
coord1':true,
'coord2':false,
'coord3':false,
'coord4':false
},
'name2': {
'coord4':true,
'coord5':false,
'coord6':false
},
'name3':{
'coord5':true
}
}
I hope someone can help me with this. Thank you
In order to find out if an object contains a property with a given name, you have a couple of choices.
You can use the in operator with a string property name:
if ("nameX" in myobject) {
// The object referenced by `myobject` (or its prototype)
// has its own property called "nameX"
}
else {
// It doesn't
}
in will check the object and its prototype. That probably doesn't matter for the simple objects you're using.
Or you can use hasOwnProperty, which only checks the object and not its prototype:
if (myobject.hasOwnProperty("nameX")) {
// The object referenced by `myobject` has its own property called "nameX"
}
else {
// It doesn't
}
So for instance, if you want to see if name1 is in myobject and, if not, add name1 referencing a blank object, you'd do this:
if (!("name1" in myobject)) {
myobject.name1 = {}; // No, add it and give it a blank object as its value
}
And similarly for the coordX properties of the objects you're referencing from myobject.nameX.
So I have a JavaScript object like this:
foo = {
"one": "some",
"two": "thing",
"three": "else"
};
I can loop this like:
for (var i in foo) {
if (foo.hasOwnProperty(i)) {
// do something
}
}
Which will loop through the properties in the order of one > two > three.
However sometimes I need to go through in reverse order, so I would like to do the same loop, but three > two > one.
Question:
Is there an "object-reverse" function. If it was an Array, I could reverse or build a new array with unshift but I'm lost with what to do with an object, when I need to reverse-loop it's properties. Any ideas?
Thanks!
Javascript objects don't have a guaranteed inherent order, so there doesn't exist a "reverse" order.
4.3.3 Object An object is a member of the type Object. It is an unordered collection of properties each of which contains a primitive
value, object, or function. A function stored in a property of an
object is called a method.
Browsers do seem to return the properties in the same order they were added to the object, but since this is not standard, you probably shouldn't rely on this behavior.
A simple function that calls a function for each property in reverse order as that given by the browser's for..in, is this:
// f is a function that has the obj as 'this' and the property name as first parameter
function reverseForIn(obj, f) {
var arr = [];
for (var key in obj) {
// add hasOwnPropertyCheck if needed
arr.push(key);
}
for (var i=arr.length-1; i>=0; i--) {
f.call(obj, arr[i]);
}
}
//usage
reverseForIn(obj, function(key){ console.log('KEY:', key, 'VALUE:', this[key]); });
Working JsBin: http://jsbin.com/aPoBAbE/1/edit
Again i say that the order of for..in is not guaranteed, so the reverse order is not guaranteed. Use with caution!
Why there is no one has mentioned Object.keys() ?
you can get Array of Object's properties ordered as it is, then you can reverse it or filter it as you want with Array methods .
let foo = {
"one": "some",
"two": "thing",
"three": "else"
};
// Get REVERSED Array of Propirties
let properties = Object.keys(foo).reverse();
// "three"
// "two"
// "one"
// Then you could use .forEach / .map
properties.forEach(prop => console.log(`PropertyName: ${prop}, its Value: ${foo[prop]}`));
// PropertyName: three, its Value: else
// PropertyName: two, its Value: thing
// PropertyName: one, its Value: some
There is no way to loop through an object backwards, but if you recreate the object in reverse order then you are golden! Be cautions however, there is nothing that says the order of the object will stay the same as it changes and so this may lead to some interesting outcome, but for the most part it works...
function ReverseObject(Obj){
var TempArr = [];
var NewObj = [];
for (var Key in Obj){
TempArr.push(Key);
}
for (var i = TempArr.length-1; i >= 0; i--){
NewObj[TempArr[i]] = [];
}
return NewObj;
}
The just do the swap on your object like this-
MyObject = ReverseObject(MyObject);
The loop would then look like this-
for (var KeysAreNowBackwards in MyObject){
alert(MyObject[KeysAreNowBackwards]);
}
This answer is similar to a couple of the others, but some users might find the code below easier to copy-paste for their own uses:
Object.keys(foo).reverse().forEach(function(key) { console.log(foo[key]) });
For an object "foo" as described in the question, this code will output the object elements in reverse order: "else", "thing", "some"
You can use
Object.keys
One thing to take care of is that it returns a sorted list of keys (if the keys are numerical). You might need to change it accordingly.
a = {'d':'stack','l':'overflow','b':'out','a':'first','z':'empty'}
out = Object.keys(a).reverse()
console.warn("When key contains characters : "+out)
a = {'1':'stack','4':'overflow','2':'out','5':'first','3':'empty'}
out = Object.keys(a).reverse()
console.warn("When key is a numerical string : "+out)