Set same function to multiple objects in javascript - javascript

I have a list of objects like this
var obj = [
{ name: "user", per: { pu: [{ end: "foo" }], ge: [{ end: "bar" }] } },
{ name: "user2", per: { pu: [{ end: "foo2" }], ge: [{ end: "bar2" }] } }
];
I want to add a new property cond which is a function to the objects in pu and ge, but when i do this, the function set to the only last object.
I loop through them then set them like so obj[0].per[itm][0].cond = func and that set to the last object only, but when i try to convert function toString() it set to all, JSON.stringfy() works as func same behavior.
Have I clone or set it in another way?

You may need to post fuller code as it's difficult to see where your error is. However, considering it from scratch, I think some nested loops to match the nested arrays will get you there.
for (let o of obj) {
for (let puObj of o.per.pu) {
puObj.cond = func;
}
for (let geObj of o.per.ge) {
geObj.cond = func;
}
}

use the below function...
const updateObject = (oldObject, updatedProperties) => {
return {
...oldObject,
...updatedProperties
}
};
then you can pass in your new function or anything you need to add like this:
obj[index].per = updateObject(obj[index].per, {cond : function() {}} ); //use a loop to add the function to all objects in array
//check your current obj
console.log(obj);

Related

Using if statement in array.forEach function statement to choose sub-object in array of objects

I cannot get an if statement to work inside a function called by a forEach array loop.
I have an array with objects, (with an object)
arrofobj = [
{"thing_id":"1a", "val": 1, "Type": "Switch","ValType":{"0":"Open","1":"Closed"}},
{"thing_id":"1b", "val": 72, "Type": "Sensor","ValType":{"0":"%"}}]
I would like to test if the Type is a switch, in order to write info in a new field of the objects of the array CatX:
- when it is, I want to use the val value to determine which ValType element to use in a new variable of array arrofobj.
- if not, I want to use the arrofobj.ValType.0 value
const getCat = function(){
if(arrofobj.Type !== 'Switch')
arrofobj.ValType'.0'
} else {
arrofobj.ValType.(arrofobj.val)
};
arrofobj.forEach(p => p.CatX = getCat() );
I am not getting the lint to accept the code, so cannot test.
1) You have to use bracket notation to access properties as strings.
2) You have to close the brackets on if/else correctly.
3) You have to return something from inside getCat to have something to assign to p.CatX
4) You have to actually send the object to getCat inside the loop.
const arrofobj = [
{"thing_id":"1a", "val": 1, "Type": "Switch","ValType":{"0":"Open","1":"Closed"}},
{"thing_id":"1b", "val": 72, "Type": "Sensor","ValType":{"0":"%"}}
];
const getCat = function( obj ){
if(obj.Type !== 'Switch') {
return obj.ValType[ '0' ]
} else {
return obj.ValType[ obj.val ];
}
};
arrofobj.forEach(p => {
p.CatX = getCat(p);
});
console.log( arrofobj );
Just to add to Shilly's answer:
1) In the long-run, if this is data you're creating yourself and not something from a 3rd-party endpoint, you'll find standardising the format of your object property key names (in camelCase) to be easier to work with. It won't introduce as many bugs to your code if they're identically formatted.
2) You can use object destructuring assignment and a ternary operator to shorten the code footprint a little.
const arrofobj = [
{ id: '1a', val: 1, type: 'Switch', valType: { '0': 'Open', '1': 'Closed' } },
{ id: '1b', val: 72, type: 'Sensor', valType: { '0': '%' } }
];
function getCat(obj) {
// Deconstruct the properties from obj
const { type, valType, val } = obj;
// Use a ternary operator to decide what to return
return type === 'Switch' ? valType[val] : valType['0'];
}
arrofobj.forEach(obj => {
obj.catX = getCat(obj);
});
console.log(arrofobj);

How to access other object sibling's value?

I'm just wondering if it's possible to refer to self (object) value inside the object sibling like below?
[
{
"name": "Zulh",
"name_uppercase": uppercase(self.name) // expects ZULH
},
{
"name": "John",
"name_uppercase": uppercase(self.name) // expects JOHN
}
]
Note:
Code for uppercase is omitted for brevity. In my real code, it's doing synchronous complex stuff and is not actually simple string case manipulation like that.
Using a GETTER
If you want to keep it dynamic and make it work even if you change the name property, you can use a GETTER to do this kind of thing:
const names = [
{
"name": "John",
get name_uppercase() {
return this.name.toUpperCase();
}
}
]
console.log(names[0].name_uppercase)
GETTER for multiple objects
You don't have to write this for every property manually! Use .forEach:
const names = [
{
"name": "John"
},
{
"name": "Mike"
}
]
names.forEach(object => {
Object.defineProperty(object, 'nameUppercase', {
get: function() { return this.name.toUpperCase() }
});
});
console.log(names[0].nameUppercase)
console.log(names[1].nameUppercase)
Using a class and a GETTER
Or as #Rajesh pointed out you can use a class instead:
class Person {
constructor(name) {
this.name = name;
}
get nameUpperCase() {
return this.name.toUpperCase();
}
}
const names = [ new Person("John"), new Person("Mike")];
console.log(names[0].nameUpperCase);
console.log(names[1].nameUpperCase);
You can't reference an object during initialization when using object literal syntax.. Inshort, that's not possible what you expect above
Well, you can use map and add additional/modified properties to you object like
data.map(o=> ({name: o.name, upper_case : o.name.toUpperCase()}))
var data = [
{
"name": "Zulh"
},
{
"name": "John"
}
];
var x = data.map(o=> ({name: o.name, upper_case : o.name.toUpperCase()}))
console.log(x)
You can use Array.forEach and update the objects in Array
var data = [{"name": "Zulh"},{"name": "John"}];
data.forEach(o=> o.upper_case = o.name.toUpperCase());
console.log(data);
Why not create a function that transforms your incoming array? A way to do it could be like this:
const value = [
{
"name": "Zulh"
},
{
"name": "John"
}
];
const transform = ( array, propertyToUpdate, propertyToCreate, transformation ) => {
return array.map( item => ({ ...item, [propertyToCreate]: transformation( item[propertyToUpdate] ) }) );
};
console.log( transform( value, 'name', 'name_uppercase', ( item ) => item.toUpperCase() ) );
You can't do this with the object literal syntax, since it's 'this' property will not be set at that time. For example, if you'd run your code in the browser, 'this' would refer to the window object.
So you'll either have to use one of the other answers or go for a 'class':
var uppercase = function( str ) {
return str.toUpperCase();
};
var Person = function( name ) {
this.name = name;
this.name_uppercase = uppercase( this.name );
};
var persons = [
new Person( 'zuhi' ),
new Person( 'john' )
];
console.log( persons );
Same can be written in ES6 class syntax.
I would suggest 2 approaches:
If you DO NOT want to change your initial array ( which is recommended ), use map which returns a new array with changed values ( calls a function for every array item ) .
See below
let arr = [
{
"name": "Zulh",
},
{
"name": "John",
}
];
const newArr = arr.map((x)=>{
x.name_uppercase = (x.name).toUpperCase()
return x
})
console.log(newArr)
If you don't mind changing your initial array, you can use forEach. Keep in mind that unlike map, forEach changes your array and so it doesn't return anything.
let arr = [
{
"name": "Zulh",
},
{
"name": "John",
}
];
arr.forEach((x)=>{
x.name_uppercase = (x.name).toUpperCase()
})
console.log(arr)
So it all depends if you want to change your current array or not
How about using a getter method?
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get
The get syntax binds an object property to a function that will be
called when that property is looked up.
foo = [
{
"name": "Zulh",
get name_uppercase () {
return (this.name).toUpperCase();
}
},
{
"name": "John",
get name_uppercase () {
return (this.name).toUpperCase();
}
}
]
console.log(foo[1].name_uppercase); //returns JOHN
Hope it helps :)

javascript object.assign for a only one property without making a copy

lets say we have object a
a = {
prop1:"something",
schema:{
array:[array of object]
}
}
and b is
b = {
array:[array of object]
}
and in the object arrays they have pretty much the same object with different values. I want to create a new object with a.schema updated from b with object.assign.
so I wrote something like Object.assign({},a.schema,b) and it returns me this
{
schema:
{
array:[array of object]
}
}
.But I don't want to create a copy of a and then copy this schema into the newly created copy of a.
I want this
newObject = {
prop1:"something",
schema:{
array:[array of object from b]
}
}
I want to create a new object which look just like a in a single Object.assign , is that possible?
This is an example of what you can do:
x = {a:1,b:[1,2,3}}
y = {c:[4,5,6]}
z=Object.assign({},{prop1:x.a},{shcema:y.c})
If it's all right to use the spread syntax, you can do this:
const a = {
prop1: 'something',
schema: {
array: [
{
aprop: 'prop',
},
],
},
};
const b = {
array: [
{
bprop: 'test',
},
{
bprop: 'test2',
},
],
};
const updated = {
...a,
schema: b,
};
console.log(updated);

can you get var name from object with nested objects with lodash?

https://jsfiddle.net/adamchenwei/Lyg2jy61/7/
RESOLVED VERSION:
https://jsfiddle.net/adamchenwei/Lyg2jy61/10/
For some reason findKey for parent top level got undefined
My objective is to get the result = 'myName' with lodash;
var obj = {
myName: {
Adam: 'Man',
},
herName: {
Eve: 'Woman',
},
};
var result = _.findKey(obj, '0'); //as you can see somehow its undefined!
var result2 = _.findKey(obj.myName, '0');
console.log(result);//objective is to get the result = 'myName' with lodash;
console.log(result2);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.4/lodash.min.js"></script>
It looks like what you're actually trying to do is get the first key of an object. To get the keys of an object, you can use _.keys. Then just retrieve the first one.
var obj = {
myName: {
Adam: 'Man',
},
herName: {
Eve: 'Woman',
},
};
console.log(_.keys(obj)[0]);
// Or if you want to do it exclusively with lodash functions
console.log(_.first(_.keys(obj)));
// or
console.log(_.head(_.keys(obj)));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.4/lodash.min.js"></script>
It's not clear what you're after exactly, but using _.findKey on the object you have posted would work like this:
https://jsfiddle.net/Lyg2jy61/8/
var obj = {
myName: {
Adam: 'Man',
},
herName: {
Eve: 'Woman',
}
};
console.log(_.findKey(obj, function(o) { return !!o.Adam; }));
If you just want the first key: _.keys(obj)[0]

Extend a JavaScript object

I'm looping inputs in a table, that don't have any form tag. I get the values correctly. I want to build with their values an object that contains multiple objects.
What i'm expecting?
alarms = { alarm: { status_id: '1', alarm_name: 'Critic', user_id_created: '30021061' }, alarm: { status_id: '1', alarm_name: 'Middle', user_id_created: '30021061' }, alarm: { status_id: '1', alarm_name: 'Bottom', user_id_created: '30021061' }, ... };
What i'm getting? The last object in the loop.
alarms = { alarm: { status_id: '1', alarm_name: 'Bottom', user_id_created: '30021061' } };
Here is the code:
var alarms = {}
$('.new_alarm').each(function() {
var status_id = $(this).children('.status').children().val(),
alarm_name = $(this).children('.data').children('input[name="alarm_name"]').val(),
user_id = $('#user_id').text();
objAux = {};
if(alarm_name) {
objAux = {
alarm: {
'status_id': status_id,
'alarm_name': alarm_name,
'user_id_created': user_id
}
};
}
alarms = $.extend(true, alarms, objAux);
});
What's wrong with the jQuery extend method? Why is not merging the objects?
If I'm not mistaken, what you want is actually impossible. It's akin to saying you want an array to have 5 values for the a[1].
You could implement this using an array instead of an object:
alarms = [{...},{...},{...}];
What you're writing is actually this:
alarms['alarm'] = {...};
alarms['alarm'] = {...};
alarms['alarm'] = {...};
alarms['alarm'] = {...};
You're overriding the same property "alarm" on every iteration.
You should be creating an Array and then push() the values on the end of an Array.
var alarms = [
{name: 'alarm1'}
, {name: 'alarm2'}
, {name: 'alarm3'}
];
var new_alarms = [];
$(alarms).each(function() {
console.log(this);
new_alarms.push(this);
});
console.log(alarms, new_alarms);
See: http://jsfiddle.net/y22Hk/

Categories

Resources