I've only recently started working with javascript and NodeJs.
I'm facing a simple problem that I am finding difficult to find answers to online.
I'm initialising an object holding a number of products each product then has a price and availability. When I try and set the price of one product, it sets the price of all the products rather than just the one i wanted to set. What am I doing wrong?
var ProdStruct = {
'price' : 0,
'available' : 0,
};
var Prods = {
'1' : ProdStruct,
'2' : ProdStruct,
'3' : ProdStruct,
'4' : ProdStruct,
'5' : ProdStruct,
'6' : ProdStruct,
'6' : ProdStruct,
'7' : ProdStruct
};
Prods['6']['price'] = 99;
console.log(Prods);
The Output:
{ '1': { price: 99, available: 0 },
'2': { price: 99, available: 0 },
'3': { price: 99, available: 0 },
'4': { price: 99, available: 0 },
'5': { price: 99, available: 0 },
'6': { price: 99, available: 0 },
'7': { price: 99, available: 0 } }
You have only one ProdStruct object, which you're referring to seven times. That is, you have something like this in memory:
+−−−−−−−−−−−−−−+
ProdStruct−−−−−−−−−−−−−−+−+−+−+−+−+−+−−>| (object) |
/ / / / / / / +−−−−−−−−−−−−−−+
| | | | | | | | price: 0 |
| | | | | | | | available: 0 |
| | | | | | | +−−−−−−−−−−−−−−+
+−−−−−−−−−−+ | | | | | | |
Prods−−−>| (object) | | | | | | | |
+−−−−−−−−−−+ | | | | | | |
| 1 |−−+ | | | | | |
| 2 |−−−−+ | | | | |
| 3 |−−−−−−+ | | | |
| 4 |−−−−−−−−+ | | |
| 5 |−−−−−−−−−−+ | |
| 6 |−−−−−−−−−−−−+ |
| 7 |−−−−−−−−−−−−−−+
+−−−−−−−−−−+
Modifying the state of that one object (changing price) modifies its state; doesn't matter which of the seven references you use to get to it to make the change or to look at the result, it's just one object.
You'd need to make a copy of the object to get the result you expect. One way is to use Object.assign:
var ProdStruct = {
'price' : 0,
'available' : 0,
};
var Prods = {
'1' : Object.assign({}, ProdStruct),
'2' : Object.assign({}, ProdStruct),
'3' : Object.assign({}, ProdStruct),
'4' : Object.assign({}, ProdStruct),
'5' : Object.assign({}, ProdStruct),
'6' : Object.assign({}, ProdStruct),
'6' : Object.assign({}, ProdStruct),
'7' : Object.assign({}, ProdStruct)
};
Prods['6']['price'] = 99;
console.log(Prods);
.as-console-wrapper {
max-height: 100% !important;
}
...but I think in your case I'd probably just have a constructor function:
function Prod() {
this.price = 0;
this.available = 0;
}
var Prods = {
'1' : new Prod(),
'2' : new Prod(),
'3' : new Prod(),
'4' : new Prod(),
'5' : new Prod(),
'6' : new Prod(),
'6' : new Prod(),
'7' : new Prod()
};
Prods['6']['price'] = 99;
console.log(Prods);
.as-console-wrapper {
max-height: 100% !important;
}
As Rick mentioned in a comment, you could have that constructor accept parameters:
function Prod(price, available) {
this.price = price || 0;
this.available = available || 0;
}
In that, if you don't provide price or available, it will have the value undefined, and that code uses the common idiom something || default to use 0 instead of undefined, making use of what I call the curiously powerful || operator. (Beware of doing this when it's valid for something to be a falsy* value.)
In ES2015 and later, you could do those defaults in the parameter list:
function Prod(price = 0, available = 0) {
this.price = price;
this.available = available;
}
The defaults will get applied if you don't provide arguments for those parameters (or if you explicitly provide undefined for them).
* "falsy" - In JavaScript, a value that coerces to false when used as a boolean is falsy. The falsy values are 0, "", null, undefined, NaN, and of course, false. All other values are truthy.
A couple of side-notes:
In JavaScript, the overwhelming convention is to only use initially-capped names for constructor functions, not for variables referring to other things. So prodStruct and prods.
A series of things like your Prods would probably be better as an array ([]), rather than an object with number-named properties.
The quotes around a property name in an object initializer are only required if the name isn't a valid identifier or a valid integer. All of your property names are, so you could leave them off.
Although Prods['6']['price'] works, it's more simply and idiomatically written prods[6].price.
Related
I have a JSON Object, which have pre and post filters for different payment types. I have to compute the possible combinations of inputs which can be passed for another API.
JSON Example:
{
"refund": {
"preFilters": {
"type": [ "1" ]
},
"postFilters": {
"flag2": [ "123", "678" ],
"flag5": [ "907", "8752" ]
}
}
Here, I need to get possible conditions that can be computed through AND, OR and NOT operators. Example, in this json I have to get the below 16 combinations:
1= type & (flag2 & flag5),
2= type & (flag2 | flag5),
3= type & (!flag2 & !flag5),
4= type & (!flag2 & flag5),
5= type & (flag2 | !flag5),
6= type & (!flag2 | !flag5),
7= type & (!flag2 | flag5),
8= type & (flag2 | !flag5),
9= type | (flag2 & flag5),
10=type | (flag2 | flag5),
11=type | (!flag2 & !flag5),
12=type | (!flag2 & flag5),
13=type | (flag2 & !flag5),
14=type | (!flag2 | !flag5),
15=type | (!flag2 | flag5),
16=type | (flag2 | !flag5)
And, also the type in preFilters and flag values in postFilters can have multiple values.I need to derive these set of possible conditions using And, Or and Not operators with values from pre and post filters.
Any advice or solution will be appreciated. Thanks
Make an array of functions matching the structure of your list of algorithms, then you can iterate the arrays in your data and apply those functions
const algos = [
(type, flag2, flag5) => type & (flag2 & flag5),
(type, flag2, flag5) => type & (flag2 | flag5),
(type, flag2, flag5) => type & (~flag2 & ~flag5)
// etc
];
const data = {
"refund": {
"preFilters": {
"type": [ "1" ]
},
"postFilters": {
"flag2": [ "123", "678" ],
"flag5": [ "907", "8752" ]
}
}
};
let output = [];
data.refund.preFilters.type.forEach(t => {
data.refund.postFilters.flag2.forEach(f2 => {
data.refund.postFilters.flag5.forEach(f5 => {
output.push({
type: t,
flag2: f2,
flag5: f5,
results: algos.map(algo => algo(t, f2, f5))
});
});
});
});
console.log(output);
I get the following object from a php file:
[
{"val1":"A","val2":"TA","val3":"5"},
{"val1":"A","val2":"TB","val3":"3"},
{"val1":"A","val2":"TC","val3":"2"}
]
I tried doing things like:
{label: {data:'val1'} }
{label: {data:'val1'[0]} }
{label: {data:['val1'][0]} }
But so far no luck to obtain the value I want.
This is the part of my code that deals with the data from the object:
var containerD1 = document.getElementById('tabD1');
var hotD1 = new Handsontable(containerD1, {
rowHeaders: true,
colHeaders: true,
columns: [
{type:'text', data: 'val2', readOnly:true},
{type:'text', data: 'val3', readOnly:true},
],
nestedHeaders: [
[{label: {data:'val1'}, colspan: 2}],
['Val2','Val3']
]
});
Since val1 value is dynamic, I can't set it as I have done for val2 and val3
So what I want to achieve is obtaining the value from val1 to be able to use it in the nestedHeaders part as the title for my table, since this value is repeated trough my object, it doesn't matter from which one I take it.
So far what I obtain is a table like this
+------+------+
| object |
+------+------+
| val2 | val3 |
+------+------+
| TA | 5 |
| TB | 3 |
| TC | 1 |
+------+------+
In the object part, in my table it says this [object Object].
So I'm guessing it's actually being read as an object instead of the value I want.
And I'm trying to get something like this:
+------+------+
| A |
+------+------+
| val2 | val3 |
+------+------+
| TA | 5 |
| TB | 3 |
| TC | 1 |
+------+------+
Code snippet to get the value of val1
{ label: { data: data[0].val1 } }
I'm not sure if I understand you correctly. If you want to obtain the value of val1 property in your objects, I would do this (since you say it doesn't matter from which element of the array you take it):
const data = [
{"val1":"A","val2":"TA","val3":"5"},
{"val1":"A","val2":"TB","val3":"3"},
{"val1":"A","val2":"TC","val3":"2"}
]
console.log(data[0]["val1"])
Alternatively, you could write:
console.log(data[0].val1) instead of the last line of code.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
var arr = [{id: 1, name: 'John'}, {id: 2, name: 'Mike'}];
var member = arr[0];
arr.splice(0, 1);
console.log(member);
You can keep accessing it because you still have a reference to it. It's no longer in the array, but it still exists. It will continue to exist until all references to it are dropped, and when they are, it becomes eligible for garbage collection.
After this:
var arr = [{id: 1, name: 'John'}, {id: 2, name: 'Mike'}];
you have something like this in memory (several details omitted):
+−−−−−−−−−−−−+
arr:Ref4875−−−−−−>| (array) |
+−−−−−−−−−−−−+ +−−−−−−−−−−−−−−+
| 0: Ref8612 |−−−−−>| (object) |
| 1: Ref4631 |−−+ +−−−−−−−−−−−−−−+
+−−−−−−−−−−−−+ | | id: 1 |
| | name: "John" |
| +−−−−−−−−−−−−−−+
|
| +−−−−−−−−−−−−−−+
+−−>| (object) |
+−−−−−−−−−−−−−−+
| id: 1 |
| name: "John" |
+−−−−−−−−−−−−−−+
(The "Ref1234" values are called object references. You never see their actual values, but you can think of them as a number the JavaScript engine uses to look up where the object is in memory.)
Then after this:
var member = arr[0];
both member and the array refer to the object, something like this:
member:Ref8612−−−−−−−−−−−−−−−−−−−−−+
+−−−−−−−−−−−−+ |
arr:Ref4875−−−−−−>| (array) | |
+−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−+
| 0: Ref8612 |−−−+−>| (object) |
| 1: Ref4631 |−−+ +−−−−−−−−−−−−−−+
+−−−−−−−−−−−−+ | | id: 1 |
| | name: "John" |
| +−−−−−−−−−−−−−−+
|
| +−−−−−−−−−−−−−−+
+−−>| (object) |
+−−−−−−−−−−−−−−+
| id: 1 |
| name: "John" |
+−−−−−−−−−−−−−−+
Then after:
arr.splice(0, 1);
the array no longer has a reference to it, but member still does:
+−−−−−−−−−−−−−−+
member:Ref8612−−−−−−−−−−−−−−−−−−−−−−−>| (object) |
+−−−−−−−−−−−−+ +−−−−−−−−−−−−−−+
arr:Ref4875−−−−−−>| (array) | | id: 1 |
+−−−−−−−−−−−−+ | name: "John" |
| 0: Ref4631 |−−+ +−−−−−−−−−−−−−−+
+−−−−−−−−−−−−+ |
|
|
|
|
| +−−−−−−−−−−−−−−+
+−−>| (object) |
+−−−−−−−−−−−−−−+
| id: 1 |
| name: "John" |
+−−−−−−−−−−−−−−+
I have the following JSON format, and I am looking to combine the "Virtual" and "Physical" objects into one by grouping by cluster and idc
[
{
"_id": {
"cluster": 1,
"idc": "LH8",
"type": "Virtual"
},
"SumCores": 112,
"SumMemory": 384
},
{
"_id": {
"cluster": 1,
"idc": "LH8",
"type": "Physical"
},
"SumCores": 192,
"SumMemory": 768
},
{
"_id": {
"cluster": 2,
"idc": "LH8",
"type": "Virtual"
},
"SumCores": 232,
"SumMemory": 469
},
{
"_id": {
"cluster": 2,
"idc": "LH8",
"type": "Virtual"
},
"SumCores": 256,
"SumMemory": 1024
}
Currently I have all of the output to screen using ng-repeat:
<div ng-repeat="item in servers | orderBy:['idc','cluster'] "><p>IDC:{{item._id.idc}} - Cluster: {{item._id.cluster}} - Type: {{item._id.type}} - Sum Cores: {{ item.SumCores }} </p></div>
Which produces something similar to:
IDC: LH8 - Cluster: 1 - Type: Virtual - Sum Cores: 192
IDC: LH8 - Cluster: 1 - Type: Physical -Sum Cores: 112
IDC: LH8 - Cluster: 2 - Type: Virtual - Sum Cores: 256
IDC: LH8 - Cluster: 2 - Type: Physical -Sum Cores: 232
Ideally I want to group this into a table with this as the ideal format:
+---------+--------------------+--------------------+
| Cluster | LH5 | LH8 |
+---------+--------------------+--------------------+
| | Physical | Virtual | Physical | Virtual |
+---------------------------------------------------+
| 1 | Value | Value | Value | Value |
| 2 | Value | Value | Value | Value |
| 3 | Value | Value | Value | Value |
| 4 | Value | Value | Value | Value |
+---------+----------+---------+----------+---------+
Obviously there is a lot more data than in my sample and value would represent the SumCores.
I also have access to the controller if you think the change would be better made in there:
Machine.aggregate( [ { $match : { $and: [ {"idc": req.query.idc }, {"customer":req.query.customer} ] } } ,{"$group":{_id: {"cluster":"$cluster","idc":"$idc","type":"$type"},"SumCores":{"$sum":"$cores"},"SumMemory": { "$sum":"$memory" }}}, { $sort : { idc : -1, cluster: 1 } } ]).exec(function(err, agg) {
res.json(agg);
});
Fiddle here: http://jsfiddle.net/8n227L2o/
I've forked your Fiddle, and now I've used Underscore.js to group and filter your data according to your example table.
http://jsfiddle.net/pdc5rvyo/1/
It is quite basic, and uses nested tables. You should be able to customize it by allowing uses to change the order of the lists for example.
Code example:
var lhSortedList = _.groupBy(servers, function(item) {
return item._id.idc;
});
$scope.lh8Virtual = _.filter(lhSortedList['LH8'], function(item) {
return item._id.type === 'Virtual';
});
Here is an overview of how to do what you want dynamically:
var lhList = ['LH5', 'LH8']; // sourced from server ?
var lhSortedList = _.groupBy(servers, function(item) {
return item._id.idc;
});
$scope.lhData = {};
lhList.forEach(function(lhName) {
$scope.lhData[lhName + 'Virtual'] = _.filter(lhSortedList[lhName], function(item) {
return item._id.type === 'Virtual';
});
$scope.lhData[lhName + 'Physical'] = _.filter(lhSortedList[lhName], function(item) {
return item._id.type === 'Physical';
});
});
I have response object which contain array:
Cars:
[0]: {
Name: 'Name1',
Color: 'Color2'
},
[1]: {
Name: 'Name2',
Color: 'Color2'
},
I want to copy the first item in the array and put it to object, Cars have to look:
Cars:
{
Name: 'Name1',
Color: 'Color'
},
If you're depicting things in memory, and Cars refers to an array containing objects, and your goal is to have Cars refer to just the first of those objects, you can do this:
Cars = Cars[0];
If the Cars variable was the only variable with a reference to the array, then the array becomes eligible for garbage collection. If the array's reference to the other object was the only reference to that object, then that other object ([1]) also becomes eligible for garbage collection.
Some ASCII-art might help here:
At first, you have this:
+-----------------+
+------+ +---------+ +--->| (object) |
| Cars |----->| (array) | | +-----------------+
+------+ +---------+ | | Name: 'Name1' |
| 0 |---+ | Color: 'Color2' |
| 1 |---+ +-----------------+
+---------+ |
| +-----------------+
+--->| (object) |
+-----------------+
| Name: 'Name2' |
| Color: 'Color2' |
+-----------------+
Then when you do:
Cars = Cars[0];
you have this:
+------+
| Cars |--------------------+
+------+ |
| +-----------------+
+---------+ +--->| (object) |
| (array) | | +-----------------+
+---------+ | | Name: 'Name1' |
| 0 |---+ | Color: 'Color2' |
| 1 |---+ +-----------------+
+---------+ |
| +-----------------+
+--->| (object) |
+-----------------+
| Name: 'Name2' |
| Color: 'Color2' |
+-----------------+
Note that nothing is pointing to the array anymore, so if garbage collection occurs, you end up with this:
+------+ +-----------------+
| Cars |----->| (object) |
+------+ +-----------------+
| Name: 'Name1' |
| Color: 'Color2' |
+-----------------+
Of course, if something else does have a reference to the array, the array wouldn't be GC'd (and similarly, if something else has a reference to the second object, it won't be GC'd). But that's what happens if we assume nothing else has those references.
check this: http://jsfiddle.net/romanian/6no49uwt/
response = [{
'Name': 'Name1',
'Color': 'Color2'
}, {
'Name': 'Name2',
'Color': 'Color2'
}]
console.log(response);
firstCar = response[0];
console.log(firstCar);
for display of console.log(), you will need firebug or some dev tool