Create two identical object with different value javascript [duplicate] - javascript

This question already has answers here:
How can I merge properties of two JavaScript objects dynamically?
(69 answers)
Closed 8 months ago.
i have to create 2 identical object, one with value 'home' and other with value 'mailing' if the condition is true I send them both otherwise I send only 'home', what can I do?
it's correct to do that?
var arrayObj = []
var reqBodyAddress = {};
reqBodyAddress.startDate = new GlideDateTime(current.u_data_inizio_contratto).getNumericValue();
reqBodyAddress.addressType = function(){
var objAddressType1 = {
home:'home'
}
var objAddressType2 = {
mailing:'mailing'
}
if(current.u_domicilio == true){
reqBodyAddress.addressType = objAddressType1 + objAddressType2;
}else{
reqBodyAddress.addressType = objAddressType1;
}
};
arrayObj.push(reqBodyAddress);
var sReqBodyData = JSON.stringify(arrayObj);

Use Object.assign(target, ...sources) [read more] which copies multiple source objects into a target object, and then use a condition on the second object. similar to this:
let a = {foo:'foo'}
let b = {bar:'bar'}
let c = Object.assign(a, (false? b : null));
console.log(c) // {foo:"foo"}
let d = Object.assign(a, (true? b : null));
console.log(d) // {foo:"foo", bar:"bar"}
Test it here
For your case, it would look like this:
reqBodyAddress.addressType = function(){
var objAddressType1 = {
home:'home'
}
var objAddressType2 = {
mailing:'mailing'
}
reqBodyAddress.addressType = Object.assign(
objAddressType1, // target
(current.u_domicilio? objAddressType2 : null) // source
)
}
Note that this doesn't return a copy and will edit the target object. If you don't want to edit any objects when using this function, you can make your target an empty object {} and put all your objects as sources like this:
reqBodyAddress.addressType = function(){
var objAddressType1 = {
home:'home'
}
var objAddressType2 = {
mailing:'mailing'
}
reqBodyAddress.addressType = Object.assign(
{}, // empty target
objAddressType1, // source 1
(current.u_domicilio? objAddressType2 : null) // source 2
)
}

use this
reqBodyAddress.addressType = {
home:'home'
...(current.u_domicilio && {mailing:'mailing'})
}
it's more readable first, and work correct. try to use const and let and avoid to use var for declaring variable in your js code.
your addressType property must get an object for value, right? so why do you use function for its value?
also you can't merge two object with + operator.
i hope this code solve your problem.

Related

Creating a new javascript object based on another object

I'm trying to create a new javascript object that'll have new key names based on another object. I'm almost there, but my code fails at the line // fails here with Uncaught TypeError: Cannot set property 'name' of undefined . Any idea how to get this right? Also, is there a more efficient way to build a new object in this case? I need it work on older IE browsers, hence this approach.
originalObj = {"name":"John","age":30,"state":"CA","country":"USA"};
objCodes = {"name":101,"age":102,"state":103,"country":104};
// newObj = {101:"John", 102:30,103:"CA",104:"USA"};
newObj = {};
for (var i in originalObj) {
if (objCodes.hasOwnProperty(i)) {
// console.log(i, originalObj[i]);
console.log(objCodes[i],originalObj[i])
newObj.objCodes[i] = originalObj[i] // fails here
}
}
console.log(newObj);
Just change the line like in the snippet below
originalObj = {"name":"John","age":30,"state":"CA","country":"USA"};
objCodes = {"name":101,"age":102,"state":103,"country":104};
// newObj = {101:"John", 102:30,103:"CA",104:"USA"};
newObj = {};
for (var i in originalObj) {
if (objCodes.hasOwnProperty(i)) {
// console.log(i, originalObj[i]);
console.log(objCodes[i],originalObj[i])
newObj[objCodes[i]] = originalObj[i] // fails here
}
}
console.log(newObj);
originalObj = {"name":"John","age":30,"state":"CA","country":"USA"};
objCodes = {"name":101,"age":102,"state":103,"country":104};
// newObj = {101:"John", 102:30,103:"CA",104:"USA"};
newObj = {};
for (var i in originalObj) {
if (objCodes.hasOwnProperty(i)) {
// console.log(i, originalObj[i]);
console.log(objCodes[i],originalObj[i])
newObj[objCodes[i]] = originalObj[i] // fails here
}
}
console.log(newObj);
Change the dotted notation to bracket notation. Reason for this is JavaScript allows only valid names with dotted notation which cannot start with numeric value.And In your case the keys are set to be 101,102...and so on, which are invalid.
Edit : Dynamic property names can be used only through bracket notations, such as in your case where the property name is set using a variable.
You can get the keys, iterate them and copy the items like this:
originalObj = {"name":"John","age":30,"state":"CA","country":"USA"};
objCodes = {"name":101,"age":102,"state":103,"country":104};
// newObj = {101:"John", 102:30,103:"CA",104:"USA"};
newObj = {};
Object.keys(objCodes).forEach(i => newObj[objCodes[i]] = originalObj[i]);

Determine if the constructor is called upon the same element in JavaScript Constructor Design Pattern

I've been using constructor pattern like this:
function Class(parameter) {
this.id = parameter;
}
let testOne = new Class('a');
let testTwo = new Class('a');
console.log(testOne === testTwo);
console.log(testOne == testTwo);
console.log(testOne.id === testTwo.id);
As you can see, my first console.log(testOne === testTwo) returns false. I think that it has to do with the fact that different instances of a new constructed objects are always different from one another even if it has the same exact properties. Is there another way to check if two objects constructed with the same exact properties other than checking their unique and identifying properties directly?
Internally js has two different approaches to check equality, for
primitives (like string) it goes for value comparison and for objects(arrays ,Date object)
it goes for reference(That comparison by reference basically checks to
see if the objects given refer to the same location in memory.)
Here is an approach to check objects equality by value
function Class(parameter) {
this.id = parameter;
}
let testOne = new Class('a');
let testTwo = new Class('a');
//console.log(testOne === testTwo);//gives false
//console.log(testOne == testTwo); // gives false
//
let testThree=testOne;
console.log(testOne === testThree);//gives true (As they both refer to the same instance in memory now)
/// objects equality by value
function isEquivalent(a, b) {
// Create arrays of property names
var aProps = Object.getOwnPropertyNames(a);
var bProps = Object.getOwnPropertyNames(b);
// If number of properties is different,
// objects are not equivalent
if (aProps.length != bProps.length) {
return false;
}
for (var i = 0; i < aProps.length; i++) {
var propName = aProps[i];
// If values of same property are not equal,
// objects are not equivalent
if (a[propName] !== b[propName]) {
return false;
}
}
// If we made it this far, objects
// are considered equivalent
return true;
}
// Outputs: true
console.log(isEquivalent(testOne, testTwo));
If you feel that method is long and complicated you can try some libraries like lodash it has built in functions for such tasks.
function Class(parameter) {
this.id = parameter;
}
let testOne = new Class('a');
let testTwo = new Class('a');
console.log(_.isEqual(testOne, testTwo));
// => true
console.log(testOne === testTwo);
// => false
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.core.js"></script>
You can create a function which compare two shallow object.
function Class(parameter) {
this.id = parameter;
}
let testOne = new Class('a');
let testTwo = new Class('a');
function compObj(obj1,obj2){
if(Object.keys(obj1).length !== Object.keys(obj2).length) return false;
for(let key in obj1){
if(obj1[key] !== obj2[key]) return false;
}
return true;
}
console.log(compObj(testOne,testTwo));

How to dynamically add sub-items to JavaScript object(JSON) [duplicate]

This question already has answers here:
Dynamically updating a JavaScript object from a string path [duplicate]
(3 answers)
Closed 7 years ago.
I am trying to create a JavaScript object and define its childs on the fly. Therefore, the sub items are dynamic and they may change in run-time.
What I have? var _obj = {};
In the next step, I would like to set some variables in runtime using a function. I can not find an efficient work around to implement the following function:
setObjValue("spaceA.spaceB.id", 1); that save 1 in the following path:
_obj.spaceA.spaceB.id = 1;
I have tried to split the key based on ., and then create the path step by step using a loop. However, since we do not have reference in JavaScript, it is not possible to achieve this.
In other words, how to make a function to add an object in the following pattern?
_obj["spaceA"]["spaceB"]....["id"] = 1;
The number of root steps is not defined before run. So I can not manually use codes. I need to achieve this dynamically like the example function above.
Try this:
function setObjValue(object, path, value) {
var pathArray = path.split('.');
for(var i = 0; i < pathArray.length; i++) {
var name = pathArray[i];
if(i == pathArray.length-1) {
object[name] = value;
} else {
if(!(name in object)) object[name] = {};
object = object[name];
}
}
return;
}
var obj = {};
setObjValue(obj, "test1.test2.sub", "123");
console.log(obj);
Recursion!
var startingObj = {};
var path = "one.two.three.four".split('.');
var val = 7;
function recursiveFun(o, p, v){
var key = p.shift(); // get the current key
if (p.length == 0){
// set key to val and exit
o[key] = val;
return;
}
o[key] = {}; // should check if this exists before overwriting
recursiveFun(o[key], p, v);
}
recursiveFun(startingObj, path, val);
http://plnkr.co/edit/TgoRS0xkXGG6J3DzFxzi?p=info
This one should do it in the most effective way
function setObjValue(path, value) {
path = path.split('.')
var obj = path[0]
// make obj the root
path.shift()
// remove root object from path
while(path.length){
// move further in tree
obj = obj[path[0]]
obj.shift()
}
// assign value
obj = value
}

is there a way to automatically create a javascript object by just assigning a property?

I am doing a project which requires to pass Perl objects to javascript via JSON. I am facing a problem in terms of "intermediate" object definition.
In Perl, object is represented by hash, and programmers don't have to define anything "in the middle". Once a property is created, all intermediate objects are automatically created as hash references. e.g.
$graph{chart}{yAxis}{title} = "Temperature Tracking";
However, once this object is passed to Javascript, if I want to add any new properties in the "intermediate" object, like:
graph.chart.xAxis.title = "Time Sequence";
I'll have an "undefined graph.chart.xAxis" error. Unlike Perl, Javascript doesn't automatically create objects if we simply assign a property for it.
At the moment I have to use below solution:
if (!graph.chart.xAxis) {
graph.chart.xAxis = {};
graph.chart.xAxis.title = "Time Sequence";
}
Unfortunately, in our project the objects passed from Perl are pretty dynamic and there are plenty of other objects that Javascript may not know. Above way makes JS code pretty lengthy and "ugly looking". Are there any better solutions to make Javascript behave like Perl, which means I don't have to create intermediate objects manually?
I'm not sure whether this meets your requirements but a simple function to create the missing objects could look like this:
function insertNode(obj, node, value) {
var segments = node.split('.');
var key = segments.pop();
var ref = obj;
while (segments.length > 0) {
var segment = segments.shift();
if (typeof ref[segment] != 'object') {
ref[segment] = {};
}
ref = ref[segment];
}
ref[key] = value;
};
var x = {};
insertNode(x, 'foo.bar.baz', 'hello world');
alert(x.foo.bar.baz); // "hello world"
Demo: http://jsfiddle.net/sNywt/1/
You may be interested in a library called steeltoe
steelToe(graph).set('chart.xAxis.title', 'Time Sequence');
not sure, if its suitable in your case, but you could check for property existence and create it if does not exist, like:
function use_or_create(obj, prop) {
return (obj.hasOwnProperty(prop)) ? true : (obj[prop] = {});
}
var graph.chart = {}; //your object
//function call to check if property exist before trying to use it
use_or_create(graph.chart, 'xAxis'); //check if xAxis exists and creates one if doesnot
graph.char.xAxis.title = "tested";
Maybe this Object extension will do:
Object.prototype.val = function(prop,val){
prop = /\./i.test(prop) ? prop.split('.') : prop;
if (prop.constructor === Array){
var objnow = this, pr;
while (pr = prop.shift()){
if (!objnow[pr]){
objnow[pr] = {};
}
if (!prop.length) {
objnow[pr] = val;
}
objnow = objnow[pr];
}
for (var l in objnow){
this[l] = objnow[l];
}
} else {
this[prop] = val;
}
}
// usage
var myO = {};
myO.val('a.b.c',3); //=> myO.a.b.c = 3
myO.val('someprop',3); //=> myO.someprop = 3
myO.val('a.b.someprop',5); //=> myO.a.b.someprop = 3

Set of objects in javascript

I'd like to have a set of objects in Javascript. That is, a data structure that contains only unique objects.
Normally using properties is recommended, e.g. myset["key"] = true. However, I need the keys to be objects. I've read that Javascript casts property names to strings, so I guess I can't use myset[myobject] = true.
I could use an array, but I need something better than O(n) performance for adding, finding and removing items.
It needs to be able to tell objects apart by reference only, so given:
var a = {};
var b = {};
then both a and b should be able to be added, because they're separate objects.
Basically, I'm after something like C++'s std::set, that can store Javascript objects. Any ideas?
ES6 provides a native Set:
let s = new Set();
let a = {};
let b = {};
s.add(a);
console.log(s.has(a)); // true
console.log(s.has(b)); // false
Here's a mad suggestion ... key it on the result of JSON.stringify(object)
It's not possible for all objects, but if your object has a .toString() method implemented, it is:
var x = {toString: function(){ return 'foo'; }};
var y = {toString: function(){ return 'bar'; }};
var obj = {};
obj[x] = 'X';
obj[y] = 'Y';
console.log(obj);
// { foo: 'X', bar: 'Y' }
If you want to make this easier, make it a class:
function myObj(name){
this.name = name;
}
myObj.prototype.toString = function(){ return this.name; }
var obj = {};
obj[new myObj('foo')] = 'X';
obj[new myObj('bar')] = 'Y';
I'm answering my own question, but I came up with an alternative solution I thought was interesting and thought it would be useful to share it.
cwolves' answer gave me an idea. Providing an object's toString() method uniquely identifies the instance, properties of an object can be used to store a set of objects. Essentially, to store object x, you can use items[x.toString()] = x;. Note that the value is the object itself, so then the set of objects can be extracted by looking at all item's properties and dumping all the values in to an array.
Here's the class, which I call ObjectSet, in full. It requires objects are uniquely identified by their toString() method, which is OK for my purposes. add, remove and contains should all run in better than O(n) time - whatever javascript's property access efficiency is, which hopefully is either O(1) or O(n log n).
// Set of objects. Requires a .toString() overload to distinguish objects.
var ObjectSet = function ()
{
this.items = {};
this.item_count = 0;
};
ObjectSet.prototype.contains = function (x)
{
return this.items.hasOwnProperty(x.toString());
};
ObjectSet.prototype.add = function (x)
{
if (!this.contains(x))
{
this.items[x.toString()] = x;
this.item_count++;
}
return this;
};
ObjectSet.prototype.remove = function (x)
{
if (this.contains(x))
{
delete this.items[x.toString()];
this.item_count--;
}
return this;
};
ObjectSet.prototype.clear = function ()
{
this.items = {};
this.item_count = 0;
return this;
};
ObjectSet.prototype.isEmpty = function ()
{
return this.item_count === 0;
};
ObjectSet.prototype.count = function ()
{
return this.item_count;
};
ObjectSet.prototype.values = function ()
{
var i, ret = [];
for (i in this.items)
{
if (this.items.hasOwnProperty(i))
ret.push(this.items[i]);
}
return ret;
};
I used Map, solved my case
const objectsMap = new Map();
const placesName = [
{ place: "here", name: "stuff" },
{ place: "there", name: "morestuff" },
{ place: "there", name: "morestuff" },
];
placesName.forEach((object) => {
objectsMap.set(object.place, object);
});
console.log(objectsMap);
For what you're trying to do (sets of objects), there is no native Javascript implementation. You would have to implement this on your own. One way to do this would be to implement a hashing function for your objects. The backing data-type of the set would be an associative array, where the key of the array is the value you get from calling the object's hash function, and the value of the array is the object itself.
Of course, this doesn't address the issue that you highlighted, so you will need to take equality into account as well (implement an equals function perhaps)?
Instead of making the hash function a property of the object itself, you can have a standalone hash function that takes in an object as input and generates a hash value (presumably by iterating over its properties).
Using this method you should be able to get O(1) for insertion, searching, and removing (not counting the order of the hash function, which shouldn't be any worse than O(n), especially if you are iterating over its properties to create your hashed value).
ECMAScript6 Set should behave like that:
Standard: http://www.ecma-international.org/ecma-262/6.0/#sec-set-o-p-v-throw
Unofficial ES6 cheat sheet: https://github.com/lukehoban/es6features#map--set--weakmap--weakset
Working example on Firefox 32 (but not implemented in Chromium 37):
if (Set) {
var s = new Set()
var a = {}
var b = {}
var c = {}
s.add(a)
s.add(b)
s.add(b)
assert(s.size === 2)
assert(s.has(a))
assert(s.has(b))
assert(!s.has(c))
}
This is not surprising since {} != {}: equality compares object addresses by default.
A module that implements it for browsers without support: https://github.com/medikoo/es6-set
Javascript Set's don't do deep object comparison.
Using lodash, this is a unique array with deep object comparison:
const objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
_.uniqWith(objects, _.isEqual);
Just typed this up, it's only briefly tested:
var Set = function Set()
{
var list = [];
var contains;
this.contains = contains = function(x) {
return list.indexOf(x) >= 0;
}
var put;
this.put = put = function(x) {
if (!contains(x))
list.push(x);
return this;
}
var remove;
this.remove = remove = function(x)
{
var idx = list.indexOf(x);
if (idx >= 0)
list.splice(idx,1);
return this;
}
var all;
this.all = all = function()
{
return list.concat();
}
return this;
}
It seems that the inner call of function works when prefixed with this.
Exemple:
var put;
this.put = put = function(x) {
if (!this.contains(x))
list.push(x);
return this;
}
Please use this code as a reference.
const fruits = [
{name: 'apple', price: 100},
{name: 'apple', price: 100},
{name: 'orange', price: 200},
{name: 'grapes', price: 300}
];
const hasFruitDuplicated = () => {
const duplicatedDeleteFruits = fruits.filter((fruit, index) =>
fruits.findIndex(item => item.name === fruit.name && item.price === fruit.price) === index
);
return duplicatedDeleteFruits;
};
Given an array of the following type:
Array<{ foo: T1, bar: T2 }>
You can build a corresponding dictionary of type:
{ [foo: T1]: Set<T2> }
The look-up for { foo: fooValue, bar: barValue } can be performed as follows:
if (fooValue in dictionary && dictionary[fooValue].has(barValue))
This way we can build what would be an ObjectSet<T1, T2>
.
If you now have three elements, you can build the following dictionary:
{ [foo: T1]: ObjectSet<T2, T3> }
and extend your ObjectSet to any number of properties by induction.
That is assuming your types can be used as index signatures.

Categories