Difference between js objects constructed in different ways - javascript

What is the difference between js objects created in this way? :
var js = {};
js.first = "blah";
js.second = something;
vs:
var js {
first : "blah",
second: something
}
In chrome inspector I don't see any problem. I've problem when passing js variable (first example) to socket.emit which gives me empty object in first case but works fine in the second example.
I'm confused.
Reference: https://stackoverflow.com/questions/20828860/why-cannot-i-pass-object-via-node-js-emit

There is absolutely no difference between these 2 ways of creating an new object.
First example just shows how dynamically you can add new keys and values to existing object.
if you try to compare them with == you will get false, but even if you create 2 objects similar way, you will get false as well...
var js = {
first : "blah",
second: something
}
var js2 = {
first : "blah",
second: something
}
js == js2 //false
so it seems to be some browser/node bug, if it's giving you empty object. Maybe parser bug? hard to say. But there is no actual difference

Related

object with array type string causing a typeError

The best way to explain this is just to show you.
var condition = 70;
var formnames = new Array("wheelcheckbox1", "wheelcheckbox2","spokecheckbox","spokecheckbox2","tirecheckbox","tirecheckbox2","tirecheckbox3");
formnames.forEach(function(entry) {
console.log(obj.entry);
if(obj.entry == "") {
condition = condition - 10;
}
});
as you can see I used the console log to show how it needs to work
as that works perfect, however, using the array causes an error as
they're strings and not what the obj wants, it wants text without it being a string.
Any ideas?
for..in should not be used to iterate over an array. Consider using forEach instead.

Use window to execute a formula instead of using eval

My code need to execute a forumla (like Math.pow(1.05, mainObj.smallObj.count)).
My path is :
var path = mainObj.smallObj.count;
as you can see.
If needed, my code can split all variable names from this path and put it in an array to have something like :
var path = ["mainObj", "smallObj", "count"];
Since I don't want to use eval (this will cause memory leaks as it will be called many times every seconds), how can I access it from window?
Tried things like window["path"] or window.path.
If it is always unclear, let me know.
Thanks in advance for any help.
EDIT: forget to tell that some config are written in JSON, so when we take the formula, it's interpreted as "Math.pow(1.05, mainObj.smallObj.count)" so as a string.
I would say there are better solutions then eval, but it depends how the forumla can be structured. It could be precompiled using new Function (this is also some kind of eval) but allowing it to be called multiple times without the need to recompile for each invocation. If it is done right it should perform better then an eval.
You could do something like that:
var formula = {
code : 'Math.pow(1.05, mainObj.smallObj.count)',
params : ['mainObj']
}
var params = formula.params.slice(0);
params.push('return '+formula.code);
var compiledFormula = Function.apply(window, params);
//now the formula can be called multiple times
var result = compiledFormula({
smallObj: {
count: 2
}
});
You can get the path part reconciled by recursively using the bracket notation:
window.mainObj = { smallObj: { count: 2 } };
var path = ["mainObj", "smallObj", "count"];
var parse = function (obj, parts) {
var part = parts.splice(0, 1);
if (part.length === 0) return obj;
obj = obj[part[0]];
return parse(obj, parts);
};
var value = parse(window, path);
alert(value);
Basically, parse just pulls the first element off the array, uses the bracket notation to get that object, then runs it again with the newly shortened array. Once it's done, it just returns whatever the result of the last run is.
That answers the bulk of your question regarding paths. If you're trying to interpret the rest of the string, #t.niese's answer is as good as any other. The real problem is that you're trusting code from an external source to run in the context of your app, which can be a security risk.

Unable to use variable in constructing $pop query in Meteor

I'm trying to use $pop on an embedded array in Meteor and I'm pretty certain that my limited understanding of variable scope and order of operations is causing me issues.
To provide a simplified example, this works:
do_thing = function(foo) {
Coll.update(foo, {$pop: { "bar.baz": 1 }} );
};
do_thing( "123" );
But this does not:
do_thing = function(foo, bar) {
var tmp = bar + ".baz"
Coll.update(foo, {$pop: { tmp: 1 }} );
};
do_thing( "123", "bar" );
The core issue is that the update succeeds when I hard-code the array from which I wish to pop the item, but the update fails when that array is dynamically constructed. I assume the cause is not the fact that it is a variable since 'foo' works, and instead the problem lies in the way that 'tmp' might not be getting instantiated in time for the update() call.
Can anyone suggest how I can achieve the result I'm looking for: popping an item from a field whose name I won't necessarily know until I'm in the function?
Alternately, I'm open to broader suggestions of how to construct this function if I'm taking a completely wrong-headed approach in the first place.
The literal string "tmp" is being used for the key name, rather than the value you are passing in for the variable "tmp".
Try this:
updateboj = {}
updateobj[tmp] = 1
Coll.update(foo, {$pop: updateobj} );

Javascript - Array of prototype functions

I'm a javascript newbie so I'm writing ugly code so far sometimes due to my lack of experience and how different it is to the languages I'm used to, so the code I'll post below works, but I'm wondering if I'm doing it the right way or perhaps it works but it's a horrible practice or there is a better way.
Basically, I have a little dude that moves within a grid, he receives from the server an action, he can move in 8 directions (int): 0:up, 1: up-right, 2: right... 7: up-left.
the server will send him this 0 <= action <= 7 value, and he has to take the correct action... now, instead of using a switch-case structure. I created a function goUp(), goLeft(), etc, and loaded them in an array, so I have a method like this:
var getActionFunction = actions[action];
actionFunction();
However, what to set all this up is this:
1) create a constructor function:
function LittleDude(container) {
this.element = container; //I will move a div around, i just save it in field here.
}
LittleDude.prototype.goUp() {
//do go up
this.element.animate(etc...);
}
LittleDude.prototype.actions = [LittleDude.prototype.goUp, LittleDude.prototype.goUpLeft, ...];
//In this array I can't use "this.goUp", because this points to the window object, as expected
LittleDude.prototype.doAction = function(action) {
var actionFunction = this.actions[action];
actionFunction(); //LOOK AT THIS LINE
}
Now if you pay attention, the last line won't work.. because: when i use the index to access the array, it returns a LittleDude.prototype.goUp for instance... so the "this" keyword is undefined..
goUp has a statement "this.element"... but "this" is not defined, so I have to write it like this:
actionFunction.call(this);
so my doAction will look like this:
LittleDude.prototype.doAction = function(action) {
var actionFunction = this.actions[action];
actionFunction.call(this); //NOW IT WORKS
}
I need to know if this is hackish or if I'm violating some sort of "DO NOT DO THIS" rule. or perhaps it can be written in a better way. Since it seems to me kind of weird to add it to the prototype but then treating it like a function that stands on its own.
What you are trying to do is one of the possible ways, but it is possible to make it more simple. Since object property names are not necessary strings, you can use action index directly on prototype. You even don't need doAction function.
LittleDude = function LittleDude(container) {
this.container = container;
}
LittleDude.prototype[0] = LittleDude.prototype.goUp = function goUp() {
console.log('goUp', this.container);
}
LittleDude.prototype[1] = LittleDude.prototype.goUpRight = function goUpRight() {
console.log('goUpRight', this.container);
}
var littleDude = new LittleDude(123),
action = 1;
littleDude[action](); // --> goUpRight 123
littleDude.goUp(); // --> goUp 123
actionFunction.call(this); //NOW IT WORKS
I need to know if this is hackish or if I'm violating some sort of "DO NOT DO THIS" rule. or perhaps it can be written in a better way.
No, using .call() is perfectly fine for binding the this keyword - that's what it's made for.
Since it seems to me kind of weird to add it to the prototype but then treating it like a function that stands on its own.
You don't have to define them on the prototype if you don't use them directly :-) Yet, if you do you might not store the functions themselves in the array, but the method names and then call them with bracket notation:
// or make that a local variable somewhere?
LittleDude.prototype.actions = ["goUp", "goUpLeft", …];
LittleDude.prototype.doAction = function(action) {
var methodName = this.actions[action];
this[methodName](); // calls the function in expected context as well
}

Using Wiki API by format JSON can't get the content

I use this code to gathering the information from Wiki:
http://en.wikipedia.org/w/api.php?action=query&rvprop=content&prop=revisions&format=json&titles=apple
And I can get a JSON String like this
{
"query": {
"normalized": [{
"from": "apple",
"to": "Apple"
}],
"pages": {
"18978754": {
"pageid": 18978754,
"ns": 0,
"title": "Apple",
"revisions": [{
"*": "Something....."
}]
}
}
}
}
I can eval it to JSON, but the problem is, I can get into the query>pages, after that I can't get deeper, it was Because the Wiki API return me as a String 18978754, but it can't get the value by this:
jsonObject.query.pages.18978754
Some assumption I need to clarify, I don't know the number 18978754. Do I need to get the number first or I can still get "Something..." within knowing the number.
What about using array-syntax :
jsonObject.query.pages[18978754]
Seems to be working, using firebug :
>>> data.query.pages[18978754]
Object pageid=18978754 ns=0 title=Apple revisions=[1]
And :
>>> data.query.pages[18978754].title
"Apple"
Note accessing data-object with an array-syntax is also possible for the other properties ; for instance :
>>> data['query'].pages[18978754].title
"Apple"
That's perfectly valid JS syntax :-)
Added after seing the comment / edit
If you don't know the ids of the pages, you can iterate over the pages, with something like this :
for (var pageId in data.query.pages) {
if (data.query.pages.hasOwnProperty(pageId)) {
console.log(data.query.pages[pageId].title);
}
}
Note that I'm using hasOwnProperty to be sure the object I'm on has the property, and that it's not coming from any kind of inheritance or anything like that :
Every object descended from Object
inherits the hasOwnProperty method.
This method can be used to determine
whether an object has the specified
property as a direct property of that
object; unlike the in operator, this
method does not check down the
object's prototype chain.
Depending on what's in "revision", you might have to do the same on that one too, btw...
Hope this helps better :-)
Second edit, after second set of comments :
Well, going a bit farther (didn't think you meant it literally) :
data.query.pages[pageId].revisions
is an array (note the [] symbols) that seems to be able to contain several objects.
so, you can get the first one of those this way :
data.query.pages[pageId].revisions[0]
The second one this way :
data.query.pages[pageId].revisions[1]
(there is no second one in the example you provided, btw -- so this is in theory ^^ )
And so on.
To get everyone of those objects, you'd have to do some kind of loop, like this :
var num_revisions = data.query.pages[pageId].revisions.length;
var i;
for (i=0 ; i<num_revisions ; i++) {
console.log(data.query.pages[pageId].revisions[i]);
}
And now, inside that loop, you should be able to get the '*' property of the given object :
data.query.pages[pageId].revisions[i]['*']
So, the final code becomes :
for (var pageId in data.query.pages) {
if (data.query.pages.hasOwnProperty(pageId)) {
var num_revisions = data.query.pages[pageId].revisions.length;
var i;
for (i=0 ; i<num_revisions ; i++) {
console.log(data.query.pages[pageId].revisions[i]['*']);
}
}
}
Using this code in firebug, I now get the literral sting you're looking for :
Something.....
Of course, you could probably just use :
for (var pageId in data.query.pages) {
if (data.query.pages.hasOwnProperty(pageId)) {
console.log(data.query.pages[pageId].revisions[0]['*']);
}
}
Which will work fine if you always want to deal with only the first element of the revisions array.
Just beware : in your example, there was only one revision ; the code I provided should be able to deal with many ; up to you to determine what you want to do with those ;-)
Late but maybe helpful for someone else.
When you add &indexpageids to your request you will get the pageids. More information here.
I had this same issue while creating a php-based parser for the Wiki API - here's how I solved it.
$new_result = array_pop($result["query"]["pages"]);
$final_result = $new_result["pageid"];
Note: I know this is PHP code in a JS question, but couldn't find exactly the same question/problem in that forum - I'm sure this will be useful for someone.

Categories

Resources