javascript object within object issue - javascript

I am trying to get the first object within an object.
I have something like
var object = {
task:{
config:'auto',
title :'test'
},
prop:'switch',
time:'5min'
}
My problem is task object could be named differently. so it could be
var object = {
task2:{
config:'manual',
title :'test2'
},
prop:'switch',
time:'5min'
}
I can't use object.task1.config because task name could changed. The task object will always be the first object though.
I want to get the task object no matter what name it has. How do I accomplish that? Thanks!

To get the first property value of an object in modern browsers you could use the Object.keys method:
var myObject = {
whoTheHellKnows: 'foo',
notUsed: 'whatever'
};
var firstProperty = myObject[Object.keys(myObject)[0]];
Working example
Edit: if you do not trust the ordering of the properties (which you should not) AND the task object is the only nested object in your objects, you can rely on type interrogation to find it:
var myObject = {
task123215452: { dahKey: 'foo' },
notUsed: 'whatever',
somethingElse: 42
};
var taskObject;
for (var key in myObject) {
if (typeof myObject[key] === 'object' && !(myObject[key] instanceof Array)) {
taskObject = myObject[key];
break;
}
}
Working example

If you need to access the first key and you don't know the key name, you should really be using an array instead of an object. Objects don't have the concept of a "first" key.
If that's not an option, you're left with for..in or Object.keys, which may fail on some JavaScript implementations because the language specification does not enforce the order of object key enumerations. However, in practice, it will work on current browsers, as they all iterate the keys in the order they were declaredcitation needed thanks to jbabey.

Related

How to copy json object without reference in vue?

In my component i have declarated some data like this:
data() {
return {
defaultValue: {json object with some structure},
activeValue: {}
...
And in component methods a make copy this value:
this.activeValue = this.defaultValue
But problem is, after change this.activeValue value a have changes in this.defaultValue too.
If i use Object.freeze(this.defaultValue) and trying change this.activeValue i have get error - object is not writable.
How i can make copy of data but without reference?
If you have simple object, quickest and easiest way is to just use JSON.parse and JSON.stringify;
const obj = {};
const objNoReference = JSON.parse(JSON.stringify(obj));
this.activeValue = { ...this.defaultValue }
Using an ES6 spread operator will help you to do a copy if you do not have a nested object. If you equate using equal = sign, it will not create a new object, it will just create a variable with the reference to the current object (like a shallow copy).
To do a complete deep copy, even it is nested object, go for this:
const objNoReference = JSON.parse(JSON.stringify(obj));
as suggested by Owl.
Click to read more for better understanding of the concept
A nicer way rather than using JSON.parse, JSON.stringify is:
this.activeValue = {...this.defaultValue}
but this is not natively supported by some browser (IE), unless used with a transpiler (babel)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
Update
Considering your originial question is about a way in Vue, there is also a native method in vue:
this.activeValue = Vue.util.extend({}, this.defaultValue)
as for this answer.
Hope this helps!
Objects are assigned and copied by reference.
All operations via copied references (like adding/removing properties) are performed on the same single object.
To make a “real copy” (a clone) we can use Object.assign for the so-called “shallow copy” (nested objects are copied by reference).
For “deep cloning” use _.cloneDeep(obj) from loadash library.
JSON stringify&parse method have some issues like converting date objects to strings. It also cannot handle special data types like Map,Set,function etc... This is prone to future bugs.
I use the following method to deep copy an object.
REMEMBER! this is not a complete application of cloning. There are more data types to handle like Blob, RegExp etc...
const deepClone = (inObject) => {
let outObject, value, key
if (typeof inObject !== "object" || inObject === null)
return inObject
if (inObject instanceof Map) {
outObject = new Map(inObject);
for ([key, value] of outObject)
outObject.set(key, deepClone(value))
} else if (inObject instanceof Set) {
outObject = new Set();
for (value of inObject)
outObject.add(deepClone(value))
} else if (inObject instanceof Date) {
outObject = new Date(+inObject)
} else {
outObject = Array.isArray(inObject) ? [] : {}
for (key in inObject) {
value = inObject[key]
outObject[key] = deepClone(value)
}
}
return outObject
}
You can use 'JSON.parse and stringify' or using some clone function in the libs like lodash (underscore, ramda...)
Also a simple solution is to store defaultValue: {json object with some structure} with JSON.stringify(defaultValue) in a string variable:
var x = JSON.stringify(this.defaultValue);
If you need it as JSON object again you can get it with JSON.parse():
var newObject = JSON.parse(x);
The object reference is also broken doing it this way, x will stay unchanged if the content of the object defaultValue is altered.

Why do we always need to check if an object has a key? - JS

I have the codes below.
var obj = {
name : 'Krysten',
age : 33,
hasPets : false
};
function listAllValues(obj) {
// your code here
var array = [];
for(var key in obj) {
if(obj.hasOwnProperty(key)) {
var value = obj[key];
array.push(value);
}
}
console.log(array);
}
listAllValues(obj);
I want to focus on this code:
for(key in obj) {
if(obj.hasOwnProperty(key)) {
}
}
Why do we always need to check if obj has its own property key?
It doesn't sounds clear to me. Anyone who can explain it to me in laymans term?
Sorry dummy here.
hasOwnProperty checks is the property of the object's itself. It may also be a property of it's prototype. So with that you check if the property belongs to the current object, not it's prototype.
Example
I have an object, which has a prototype. With pure for in it prints all properties, also that ones which are in the prototype (id). But with the second one, it prints only that ones which belongs to the object itself.
var parent = {
id: 1
};
var obj = {
name: 'Test',
age: 18
};
Object.setPrototypeOf(obj, parent);
// All properties, also the prototype's. See the `id` property
console.log('All properties');
for(var key in obj){
console.log(key);
}
console.log('Only it\'s properties');
// All properties that belong only to object
for(var key in obj){
if(obj.hasOwnProperty(key)) {
console.log(key);
}
}
It's a remnant from darker times, when JS wasn't that sleek and its developers more coarse. When everybody extended basic prototypes and we didn't have the ability to define non-enumerable properties.
So you never knew what properties ended up on your objects due to inheritance; that's when we introduced this practice of checking wether it's an own property. That's also where it started to be considered a bad practice to extend foreign prototypes.
But these were rougher, darker times. Times when you needed mental strength to write JS. When you needed wisdom to write a function that worked in multiple browser, and nerves of steel to approach or even modify someone elses code never knowing what bain you may bring upon you 😁
Nowadays I'd immediately abandon a foreign lib that would be so ruthless to randomly modify the basic prototypes (with very few exceptions), especially if it doesn't make these extensions enumerable:false.

Access property within javascript object [duplicate]

This question already has answers here:
Get property of object in JavaScript
(3 answers)
Closed 6 years ago.
I am trying to access a property within an object and return it.
Note the name of the object can change, so accessing it using title_can_change.property will not work.
Take the following object:
{
"title_can_change":{
property: 1
}
}
How do I return the value of 'property'?
MORE INFO:
This object is being returned from a search which contains an array of results from several API's. This object is returned to detail the API the result has come from (the search goes through several API's).
So this would be more like:
apiData:{
"apiName":{
price: 500
}
}
"apiName" is not fixed and changes to say the name of the API. So it cannot be referenced by "apiName' in any of the code.
You could create a function to return the value of the property of whatever object you pass to it:
var getProperty = function(obj) {
return obj.property;
};
If you have an object and you want to access it's first key's value you can go with something like this (dirty example):
var myObj = {
"title_can_change"{
property: 1
}
}
myObj[Object.keys(myObj)[0]];
I home this helps.
So I think I know what you are wanting and here is a low-level solution that may prove valuable and show you some neat things about the language.
https://jsfiddle.net/s10pg3sh/1/
function CLASS(property) {
// Set the property on the class
this.property = property || null;
}
// Add a getter for that property to the prototype
CLASS.prototype.getProperty = function() {
return this['property'];
}
var obj = new CLASS(9);
alert(obj.getProperty());
What you are doing in the above is creating a "class" for your new variable. When you create your object with the new keyword as show you still get your normal JS object (everything is an object anyways), but you get the convenience of the getProperty method. This being on the prototype insures that any new CLASS variables you create will have that method. You can change the variable names and you will always have access to that property by having access to the instance (variable). This is a very common OO paradigm and is the strength of a prototypical language so while it may be over the top for your needs I figured I would add it as an answer here...
If this object is global, then you can use window['title_can_change']['property']. If it's just another property of another object (called another_one) you can access it with another_one['title_can_change']['property'].
Furthermore: You can have a variable (let's call it title_name) to ease the call:
....
var title_name = "title_can_change";
var myObj = window[title_name]['property'];
title_name = "title_has_changed";
var anotherObj = window[title_name]['property'];
.....
OR
....
var title_name = "title_can_change";
var myObj = another_one[title_name]['property'];
title_name = "title_has_changed";
var anotherObj = another_one[title_name]['property'];
.....
Kind of a guess here since the question is still somewhat unclear. I am assuming that you want to iterate over an objects properties whose names are unknown.
This might be a solution.
for (var property in object) {
if (object.hasOwnProperty(property)) {
// check objects properties for existence
// do whatever you want to do
}
}
Use for...in to iterate over the keys of the object and check if your inner object contains your property
var o = {
"title_can_change":{
property: 1
}
};
for (var k in o) {
if (o.hasOwnProperty(k) && o[k].property) {
return o[k].property;
}
}

If value is in Object javascript

Without using a for is there a way to determine if an object has a value.
var obj = {1: 'j', 54: 1, 29018: 4};
I am looking for something like.
obj.indexOf('j');
I do not really care what the index is just if it's in the object without having nested items.
I am aware I could do, but I am looking for another solution. As this one is really no better than a for.
var array = $.map(obj, function(value, index) {
return [value];
});
array.indexOf('j');
You can use Object.keys() to loop over object properties and Array.prototype.some() to check if at least one property fulfill condition (ES6 syntax):
Object.keys(obj).some(key => obj[key] === 'j'); // true
ES5 equivalent:
Object.keys(obj).some(function(key) { return obj[key] === 'j' });
In the future, you might be able to use Object.values to get an array with the values of an object, and [].includes to check if an array includes some item.
Object.values(obj).includes('j');
However, the former is only a proposal, and the later has only been standardized in a draft.
In case you want to check in the same object multiple times, better store the values in a set. Unlike arrays, searches are required to be sublinear on average (constant if implemented using a hash).
var values = new Set(Object.values(obj));
values.has('j'); // true
values.has('z'); // false
Every possible solution for this problem will involve a for loop or equivalent. Even if you use a jQuery function as in one of the examples in your question, or if you use a built-in JavaScript function as in some of the answers, there will be a for loop down inside the implementation of those functions.
This is because of the way JavaScript engines represent objects. They typically use a hash table or equivalent, where the object's property names are the keys into the hash table.
This allows fast lookup of property names without iterating over all the object's properties. But there's no hash table going the other way, where the property values are the keys. The only way to find out if a particular value exists in an object is to loop over all the properties - whether you do that yourself with a for loop, or whether you call a library function that hides the for loop.
Of course, it's a great idea to hide that for loop so you don't have to write it out every time. That's what the various library functions do for you. Or, we could go back to first principles and write our own function for this:
// Find a value in an object and return the property name that
// contains that value, or null if not found.
function findValue( object, value ) {
for( var name in object ) {
if( object.hasOwnProperty( name ) ) {
if( object[name] === value ) {
return name;
}
}
}
}
var obj = { a:'abc', d:'def': g:'ghi' };
console.log( findValue( obj, 'def' ) ); // 'd'
console.log( findValue( obj, 'foo' ) ); // null
The point is that no matter what library function or other solution you find for this, somewhere under the hood will be a for loop very much like the one above.
On the other hand, you don't have to run that for loop every time you look up a value! Even if JavaScript engines don't create a reverse index of the the object (where the object values are keys into the internal hash table), you can create one yourself.
Here's a way you could do that in any old browser:
function ReverseIndex( object ) {
this.index = {};
for( var name in object ) {
if( object.hasOwnProperty(name) ) {
this.index[ object[name] ] = name;
}
}
}
ReverseIndex.prototype.find = function( value ) {
if( this.index.hasOwnProperty(value) ) {
return this.index[value];
}
return null;
};
var obj = { a:'abc', d:'def', g:'ghi' };
var index = new ReverseIndex( obj );
console.log( index.find( 'def' ) ); // 'd'
console.log( index.find( 'foo' ) ); // null
As you can see, there is still a for loop involved here, when the ReverseIndex is first created. But unlike the first solution, the subsequent calls to index.find() do not require any looping. If you will be searching for values inside the object repeatedly, this could be faster than the first solution because it only has to loop over the object once.
You would need a bit more code if additional properties may be added to the object after you create the ReverseIndex - but I'll leave that as an exercise for the reader at the moment.
And also note that this code assumes that the object values are strings (or convert readily to strings). If the object values are other types, this won't work. See Oriol's answer for a very clean way to do this lookup using a set in modern browsers.

Associative array versus object in JavaScript

In my script there is a need to create a hash table, and I searched in google for this. Most of the folks are recommending JavaScript object for this purpose. The The problem is some of the keys in the hash table have a "." in them. I am able to create these keys easily with the associative arrays.
I don't understand why associative arrays are bad. The first thing that is mentioned on the sites that I looked at is the length property.
I am coming from the Perl background, where I used hashes. Most common uses were to get the value from a key, check if a key exists, delete a key-value pair, and add a key-value pair. If these are my common uses, can I safely use an associative array?
In JavaScript, objects are associative arrays...there aren't separate concepts for them. You are also able to safely use '.' in a key name, but you can only access the value using the bracket notation:
var foo = {}
foo['bar'] = 'test';
foo['baz.bin'] = 'value';
alert(foo.bar); // Shows 'test'
alert(foo['baz.bin']); // Shows 'value'
If you're using them already and they work, you're safe.
In a JavaScript, an object and array are pretty much the same thing, with an array having a bit of magical functionality (autoupdating the length property and such) and prototype methods suitable for arrays. It is also much easier to construct an object than using an associative array:
var obj = {"my.key": "myValue"};
vs.
var obj = [];
obj["my.key"] = "myValue";
Therefore never use the array object for this, but just the regular object.
Some functionality:
var obj = {}; // Initialized empty object
Delete a key-value pair:
delete obj[key];
Check if a key exists:
key in obj;
Get the key value:
obj[key];
Add a key-value pair:
obj[key] = value;
Because there is no such thing as built-in associative arrays in JavaScript. That's why it's bad.
In fact, when you use something like:
theArray["a"] = "Hello, World!";
It simply creates a property called "a" and set its value to "Hello, World!". This is why the length is always 0, and why the output of alert(theArray) is empty.
Actually, an "associative array" is pretty much the same as an "array-like object" in ECMAScript. Even arrays are objects in ECMAScript, just with the exception to have numeric keys (which are still strings in the background) and a .length property, along with some inherited methods from Array.prototype.
So, a Perl hash and an ECMAScript object behave similarly. You might not know that you can access object properties not only via a dot, but also with brackets and strings, like
var myObj = { foo: 42 };
myObj.foo; // 42
myObj['foo']; // 42
Knowing that, you can also use keys with .
var myObj = { };
myObj['hello.foo.world'] = 42;
Of course, you can access that key only with the bracket notation.
You can use . in key names on JavaScript objects (AKA associative arrays) if you'd like; they're accepted without issue. The minor drawback is you can't use shortcut notations with the dotted keys, e.g.
var x = {};
x['hello'] = 'there';
alert(x.hello);
is perfectly acceptable and will pop up an alert with 'there' in it. But if you use a dotted name:
var x = {};
x['this.is'] = 'sparta';
alert(x.this.is);
will fail, as JavaScript will look for an attribute named this in the x object, which does not exist. There is only the this.is attribute.
There isn't an associative array. It's just an object.
foo.bar; // Equivalent to...
foo["bar"]; // Looks like associative array.
For the sake of convenience of using data, there should be no difference between an object and an array. You can think of it as an object or you can think of it as an associative array. At the end, you can just think of everything as data.
For PHP, [ ] accepts 0, 1, or more items(array), and it is called an associative array. It is JSON in PHP's coat:
$data = ["message"=>[ "id"=>405, "description"=>"Method not allowed.", "detail"=>[]], "object" => []];
For JavaScript, { } accepts 0, 1, or more items(array), and it is called an object. This data format is JSON:
data = {"message": { "id":405, "description":"Method not allowed.", "detail" : {}}, "object" : {}};
I just call them data. The simplest way to describe data is JSON, or its variants.

Categories

Resources