Why a reference to object is replaced with its value - javascript

I use node.js and express.
I saved on the 'req.session' a complex object that includes array of objects.
In addition I save reference to one of the objects in the array.
For example:
var value = {
name: "name"
, values: []
};
req.session.value = value;
//
// I populate 'req.session.value' with values (with the same structure)
//
// then I save reference to one of the inner objects
var currentValue = req.session.value[3];
//
// later I try to change the save object
//
currentValue.name = "newName";
I expected that if I change the 'currentValue' then the 'req.session.value[3]' will be changed as well. However, for some reason it doesn't happen.
To be concrete, if I change the currentValue immediately after I assign it then the req.session.value[3] is changed but if I am doing it in the next call then just the currentValue is changed.
In the example: I do the assignments to the 'req.session' in the "app.get(...)" if I change the value of the currentValue in the "app.get(...)" it is run ok (the value change in both places) but if I change it in the 'app.post(...)' the only object that change is the currentValue while the req.session.value[3] left the same.
Thanks in advance,
Shai
The code:
'app.get("/template/:templateid/feature/add", isTemplate, function(req, res) {'
' if (!req.session.features) { // if features empty'
''
' // Save the first features level from the current template in the session '
' req.session.features = req.session.template.feature;'
' //'
' if (!req.session.featureNodes) { // featureNotes is a stack/branch of the features'
' req.session.featureNodes = [];'
' }'
' if (!req.query.featureroot || req.query.featureroot == "") {'
' } else {'
' var featureRoot = getFeature(req.query.featureroot, req.session.features); // get one object from req.session.features'
' if (featureRoot) {'
' req.session.featureNodes.push(featureRoot); // save reference'
' var featureR = req.session.featureNodes.pop(); // do check that work!'
' var values = {'
' name: "req.body.name"'
' , description: "req.body.description"'
' , wieght: "req.body.wieght"'
' , created: new Date()'
' , modified: new Date()'
' , feature: []'
' };'
''
' featureR.feature.push(values); // also req.session.features changed'
' req.session.featureNodes.push(featureRoot); // push the reference back for use later'
' } '
' }'
' res.render("addfeature2template.jade", { '
' title: "Add new feature"'
' ,template: req.session.template'
' ,feature: req.session.featureNodes'
' });'
'});'
''
'app.post("/feature/add", isUser, function(req, res) {'
' var SUBMIT = "Create";'
' var CANCEL = "Cancel";'
' switch ( req.param("feature") ) {'
' case SUBMIT:'
' var fields = { name: 1, description: 1, wieght: 1};'
' var values = {'
' name: req.body.name'
' , description: req.body.description'
' , wieght: req.body.wieght'
' , created: new Date()'
' , modified: new Date()'
' , feature: []'
' };'
' if (req.session.featureNodes.length < 1) {'
' req.session.features.push(values);'
' } else {'
' var featureRoot = req.session.featureNodes.pop(); // pop the reference'
' featureRoot.feature.push(values); // change the object but the req.session.features didnt changed '
' }'
' req.session.template = template;'
' res.redirect("/template/" + req.body.templateid);'
' break;'
' case CANCEL:'
' res.redirect("/template/" + req.body.templateid);'
' break;'
' }'
'});'

req.session object is serialized (to store) between the requests.
Example:
Request 1:
req.session = {};
var a = { hello : 'world' };
var b = a;
req.session.a = a;
req.session.b = b;
In this context variables a, b, req.session.a, req.session.b points to one object. You can change field hello in any of these objects, and this will to change in each of them.
After end of request req.session object will be serialized for session storage (memcached, mongodb, etc).
Request 2:
Before request 2 req.session object will be deserialized from storage. Now it contains plain values without references. You can access req.session.a and req.session.b but now it two different objects.

Related

How to exclude undefined parameters in a closure?

A JavaScript practice question on closures says the following:
Change the function to support multiple function calls:
function joinWords(a, b) {
return console.log(a + ' ' + b);
}
See example cases below for example inputs and their expected outputs.
Input 1:
const greet = joinWords("Hello");
greet("world);
Output 1:
"Hello World"
Input 2:
const greet = joinWords("Hey", "there!");
greet("Where", "is", "Foo", "Bar?");
Output 2:
"Hey there! Where is Foo Bar?"
For the solution, I've successfully implemented a closure, but I'm still console logging undefined parameters. AKA, for the first test case (Input 1 and Output 1) I'm outputting Hello undefined World undefined undefined undefined. How can I elegantly exclude undefined parameters here?
function joinWords(a, b) {
return function(c, d, e, f) {
console.log(
a + ' ' + b + ' ' + c + ' ' + d + ' ' + e + ' ' + f
);
};
}
You might be looking for rest parameters, which make the function accept any number of arguments and passes them over as an array (which one can then call the .join method on):
function joinWords(...values) {
return values.join(" ");
}

Javascript where clause for string that begins with text

Here is a sample of the Javascript, that I want to add an additional WHERE statement to the CONDITIONS variable.
In addition to Where Cost > 0, only include records where ProductName begins with "XYZ".
Maybe: AND ProductName StartsWith('XYZ') ??
REPORTS: [{NAME: 'MYREPORTNAME',
CONDITIONS: 'WHERE Cost > 0',
FIELDS: {'ProductSKU' : 'STRING',
'ProductName' : 'STRING',
'Cost' : 'FLOAT'
}
This is later called in this function:
function retrieveMyReport(reportConfig, ClientId) {
var fieldNames = Object.keys(reportConfig.FIELDS);
var report = MyApp.report(
'SELECT ' + fieldNames.join(',') +
' FROM ' + reportConfig.NAME + ' ' + reportConfig.CONDITIONS +
' DURING ' + CONFIG.DEFAULT_DATE_RANGE);
...
How do I expand this WHERE clause to include both conditions?
This looks like an SQL query, so you should probably use the LIKE operator:
CONDITIONS: 'WHERE Cost > 0 AND ProductName LIKE \'XYZ%\''

Array with repeating structure

I am creating a script that would show the keys of my array, in the first attempt worked perfectly, but when I added but a while block, he did not execute and returned this error:
classificacao-v2.js:128 Uncaught TypeError: Cannot read property 'Period' of undefined
at classificacao-v2.js:128
Realizing that my problem was in the variable 'n' that appeared as undefined, so I created other variables with different names for each structure.
I wonder if it is possible to rewrite it more efficiently without having to repeat each block.
let GoldemStates = [{Period: ' 1°',Points:'300'},
{Period: ' 2°',Points:'250'},
{Period: ' 3°', Points:'155'}]
let Chicago = [{Period: ' 1°',Points:'100'},
{Period: ' 2°',Points:'420'},
{Period: ' 3°', Points:'350'}]
let Broklyn = [{Period: ' 1°',Points:'300'},
{Period: ' 2°',Points:'250'},
{Period: ' 3°', Points:'155'}]
// Show the Teams
icons('','Match Results ','div_titulo')
let n = 0
icons('golden','Golden States', 'destaque_golden') //Team Title (Symbol, Team Name, CSS)
//Goldem States Statistics
do {
icons('clock',GoldemStates[n].Period + ' Period | ' + 'Points ' + GoldemStates[n].Points ,'texto') // // Show period and points
n ++
} while (n < GoldemStates.length);
let d = 0 // <-------- CHANGE WHICH WOULD NEED
//Chicago Bulls Statistics
icones('bulls','Chicago Bulls', 'destaque_bulls')//Team Title (Symbol, Team Name, CSS)
do {
icons('clock',Chicago[d].Period + ' Period | ' + 'Points ' + Chicago[d].Points ,'texto')// Show period and points
d ++
} while (d < Chicago.length);
Console Output
I think your code could be simpler, shorter and easier to read if you leave the iteration to array built in methods. That way you will remove the need to use an iteration variable and access each item:
GoldemStates.forEach(
item => icons('clock',item.Period + ' Period | ' + 'Points ' + item.Points ,'texto')
)
But we can do it eve better. Since all the teams render exactly the same, we can build a function that renders one single item and then let the methods specialized on iteration do their work. That way your code only takes care of rendering and the built-in methods takes care of iterating, separation of conerns:
const renderTeam = team => icons('clock',team.Period + ' Period | ' + 'Points ' + team.Points ,'texto')
// Render part
icons('golden','Golden States', 'destaque_golden') //Team Title (Symbol, Team Name, CSS)
GoldemStates.forEach(renderTeam)
icons('bulls','Chicago Bulls', 'destaque_bulls')//Team Title (Symbol, Team Name, CSS)
Chicago.forEach(renderTeam)

Javascript for while with mysql update when not having value

I will Update a Value in my Database when this is not setted.
I have this Code:
items.forEach(function(item,i,arr){
mysqlConnection.query('UPDATE `SkinBank` SET `AssetID`=\'' + item.assetid + '\', `Status`=\'market\' WHERE `Status`=\'open\' AND `Tradeoffer` = \'' + offer.id + '\' AND `SkinName` = \'' + item.market_hash_name + '\'', function (err, row, fields) {});
});
When i put than 2 "Items" which has item.assetid (like: Item 1 has = 123123 and Items 2 has= 987987) than all two items who has nothing get the same Assetid value like 123123 or 987987.
How i can make, that he gives every item ONE AssetId.
Before this, the column "AssetID" has nothing in there
I'm guessing that your WHERE clause is matching too many rows. It's not clear what library you are using, but if you are using node-mysql you can output the number of rows updated in the callback function:
connection.query('UPDATE `SkinBank` SET `AssetID`=\'' + item.assetid + '\', `Status`=\'market\' WHERE `Status`=\'open\' AND `Tradeoffer` = \'' + offer.id + '\' AND `SkinName` = \'' + item.market_hash_name + '\'', function (err, result) {
if (err) throw err;
console.log('changed ' + result.changedRows + ' rows');
})
https://github.com/felixge/node-mysql#getting-the-number-of-changed-rows

Parsing Complex JSON Javascript

I am able to parse JSON that returns simple data, with JSON.parse but I am having trouble with data that returns objects, dates, strings, etc..
var theData=JSON.parse(theData);
Something like this JSON.parse returns [Object] object back with no data at all (I can see the data is being successfully returned because it returns all the data as a string if I have JSON.parse turned off).
{
"AppName": "TheName",
"AppUrl": "https:\/\/app\/icons\/unknown.png",
"aGUID": "45c055d2-2edc-d4444"."DateCreated": "8\/23\/2012 11:04AM", {
"ID": "yser123",
Name ":" User "}
}
What is the best way to go about parsing this data in javascript(I am not able to use jquery)?
Note: I had wrote the JSON assume its valid
Here is the code I am using to retreive the data..
var xhReq = new XMLHttpRequest();
xhReq.open("POST", "ClientService.svc/REST/GetDetail", false);
xhReq.send(null);
var serverResponse = xhReq.responseText;
alert(serverResponse);
return serverResponse;
First and foremost, don't use synchronous XHR. Rewrite your JavaScript to be asynchronous.
function getDetail(cb) {
var xhReq = new XMLHttpRequest();
xhReq.open("POST", "ClientService.svc/REST/GetDetail", true);
xhReq.onreadystatechange = function() {
if (xhReq.readyState == 4) cb(xhReq.responseText);
}
xhReq.send(null);
}
// to call:
getDetail(function(data) {
JSON.parse(data);
}
Second, your problem is not that JSON is being parsed incorrectly. It's your debugging call to alert. When you pass the serverResponse object, alert coerces the object into a string by calling the object's toString method, which simply returns '[object Object]'.
Try console.log. Objects can be inspected in the console.
It actually sounds like this is working. If you call some thing like this:
alert(JSON.parse(serverResponse))
It will display [object Object] which is correct. If you call
alert(JSON.parse(serverResponse).appName)
You should see the appName. If you are not seeing "SyntaxError"s being thrown, JSON.parse() is working
Your JSON format is wrong and the data needs to be a string.
So, this will work (I broke the lines to improve readability):
var data = "{" +
" \"AppName\": \"TheName\", " +
" \"AppUrl\": \"https:\/\/app\/icons\/unknown.png\", " +
" \"aGUID\": \"45c055d2-2edc-d4444\", " +
" \"DateCreated\": \"8\/23\/2012 11:04AM\", " +
" \"foo\": { " +
" \"ID\": \"yser123\", " +
" \"Name\":\"User\"" +
" }" +
"}";
var obj = JSON.parse(data);
alert( obj.AppName );
Of course, if you use simple quotes as string delimiter, the code would be:
var data = '{' +
' "AppName": "TheName", ' +
' "AppUrl": "https:\/\/app\/icons\/unknown.png", ' +
' "aGUID": "45c055d2-2edc-d4444", ' +
' "DateCreated": "8\/23\/2012 11:04AM", ' +
' "foo": { ' +
' "ID": "yser123", ' +
' "Name":"User"' +
' }' +
'}';
This not works:
var data = "{" +
" 'AppName': 'TheName', " +
" 'AppUrl': 'https:\/\/app\/icons\/unknown.png', " +
" 'aGUID': '45c055d2-2edc-d4444', " +
" 'DateCreated': '8\/23\/2012 11:04AM', " +
" 'foo': { " +
" 'ID': 'yser123', " +
" 'Name': 'User'" +
" }" +
"}";
jsFiddle: http://jsfiddle.net/9pmdm/1/

Categories