I am trying to learn JavaScript. After reading this page: What does ':' (colon) do in JavaScript?
I tried to replace
var store = new dojo.data.ItemFileReadStore({
url: "countries.json"
});
with
var store = new dojo.data.ItemFileReadStore();
store.url = "countries.json";
It does not work. Can any one please point out the mistake, or explain the correct use of the Colon operator?.
Thanks.
That's not a fair comparison, although you're almost there.
var store = new dojo.data.ItemFileReadStore({
url: "countries.json"
});
//Creates a new store object, passing an anonymous object in with URL
// property set to "countries.json"
The alternative without the colon operator is:
var props={};
props.url="countries.json"
var store = new dojo.data.ItemFileReadStore(props);
//Does same as above but doesn't use :
Not this isn't the only use of : in JavaScript though, it can also be used in the ternary operator (alert(b==c?'equal':'not equal');) and in labels (for example in case statements)
The first passes url parameter to the so-called constructor or the object, which may do something under the hood with it - for example assign it to other variable or property, for example "url2".
The second assigns url property of that object and you don't know if it will be used.
In first code you are creating a new object and passing it to the function as an argument.
While in second part you are running the function and then, you are setting property of store object.
They are totally different thing, as you are not calling function with argument, so it might not run properly. and you are setting return of function to object. not setting property.
In this case, the object literal in your first example is being used to pass in a set of options to the constructor. Constructing the ItemFileReadStore and then trying to set those options may not be equivalent since it may need them in order to build the object to begin with.
You'd need to do something like this to replace : with =:
var options = {};
options.url = 'countries.json';
var store = new dojo.data.ItemFileReadStore(options);
If the second way isn't working, you're probably not returning an Object with new dojo.data.ItemFileReadStore(); which prevents you from extending it with dot syntax. If you have an Object, adding to it like that will work fine.
Edit: Misread, in one you're passing an argument, in the other you're assigning to the return value, so two different things, I'll leave the above as an FYI.
The dojo.data.ItemFileReadStore object probably requires that the url property be present while the object is being created. If that's not the case, then the object doesn't allow you to set that property manually after you have already initialized the object.
The colon is used in JSON to designate the different between a key and a value, when you pass an object structure ({}).
Related
I am trying to return the value under the key 'str' in an Object but I am having trouble accessing the value.
This is what is returned in the console:
Currently I am using a map function to go over the array and just return the _str value like so:
let idx = currentArray.map(function(x) {
return x._id._str;
});
However it is still returning the value as an object. How can I get just the value of the _str key?
Here is the full array without specifying the id field. This is what is returned if you jsut return 'x' in the map function.
You've clarified that the screenshot is of x._id. So to access _str, you'd use x._id[0]._str: The _str property is in the object referenced by the 0 property (the first entry in the array x._id refers to).
Note that in general, _-prefixed properties are meant not to be accessed by code outside the code responsible for the objects in question. You don't seem to be responsible for them, so accessing those properties is likely to make your code rely on undocumented properties that may change in the next "dot" release of whatever lib you're using. It's just convention, but it's a very common convention.
If you right click on the property, most browser consoles offer the ability to copy property path.
Based on this SO post and the docs, it appears that you can probably use x._id.str.
If I understand correctly, you are receiving the str value but it is an object instead of the string literal. In other words, you are getting _str: "598..." instead of "598....". A possible solution would be to use the mongo javascript function to convert the str value to a string.
In your case, I think something like return x._id.str; may work as _id is a MongoID.ObjectID.
I've also linked the documentation below for reference.
https://docs.mongodb.com/manual/reference/method/ObjectId/
Here's a relevant SO answer as well: Convert ObjectID (Mongodb) to String in JavaScript
I think you should write x[_id]._str because _id is one of the array objects.
I'm struggling a lot with Javascript prototyping; I don't seem to understand when I should be declaring an attribute in the prototype vs instantiation. Particularly, I don't understand, why in my code attached (a basic exercise in building a little Router class to treat a document more like an app than a page), attributes set at instantiation are persisting and thus accumulating in what I intend to be separate objects entirely.
Mostly this is a learning exercise, but I've scaled back some of the original code to help with contextual obfuscation*.
Code is here: http://codepen.io/anon/pen/xGNmWM
Basically, each time you click a link, the data-route attribute on the element should be picked up an event listener, a new Route object should be instantiated (and passed information about the intended route); finally the Router class should actually "launch" the Route, ie. make an ajax request or do some in-document stuff, whatever.
Right now, the Route.url.url attribute should be, in my obviously wrong understanding, created anew each time and then informed by passed data. Somehow, this attribute is persisting and thus accumulating passed information from each click.
I truly don't understand why.
**I have not removed anything that would effect my question; really it could be trimmed back even more but I realize the integrity of the question relies on a reasonable facsimile of the original code.
You have two problems.
By Value vs By Reference
In Javascript primitive types, as numbers, booleans and strings, are passed to another functions or set to another variable by value. That means that its value is copyed (cloned).
The object types, as objects, arrays and functions, are passed to another functions or set to another variable by reference. That means that variables of this type are just references to a content to memory. Then when you set an object to a variable, just its memory address is being copied.
When you pass the "route_data" its reference is copied. Then the Route constructor is working on same variable hold by Router.
If you clone your object before pass it the problem is solved.
...
var route_data = this.route_data[ route_name ];
route_data = $.extend(true, {}, route_data); // Clone object using jQuery
var route = new Route( route_name, route_data, request_obj);
...
Prototype
The Javascript has a prototypal inheritance, that means that each object points to its prototype that is another object.
var obj = { name: 'John' };
console.log(obj.__proto__);
All objects root prototype is Javascript Object by default. As noted by example above.
function Person(name) {
this.name = name;
}
Person.prototype = {
getName: function() {
return this.name;
}
}
var obj = new Person('John');
console(obj.getName());
console(obj.__proto__);
console(obj.__proto__.__proto__);
When you use new a new empty object is created and binded as this to specified function. Additionally its object prototype will point to the object specified on prototype of called function.
On get operations the Javascript engine will search on entire prototype chain until specified field is found.
But on set operations if the specified field does not exist on current object, a new field will be created.
When you define the url field on Route this should be static, because when you try to change it a new field is created.
If you verify your Route instance you will note that you have created duplicated url fields. One on object itself and another on prototype.
I would have really appreciated a minimal code example posted here on SO rather than codepen. It would have saved me some time reading your code (you're not paying me for this after all).
Anyway, this is problematic:
Route.prototype = {
// etc..
url : {url: false, type: "get", defer: false}
// etc..
}
Basically, what you're doing is this:
var global_shared_object = {url: false, type: "get", defer: false};
Route.prototype.url = global_shared_object;
Do you see the problem? Now when you do:
var route1 = new Route();
var route2 = new Route();
Both the .url property of route1 and route2 point to the same object. So modifying route1.url.url will also modify route2.url.url.
It should be noted that route1.url and route2.url are different variables. Or rather different pointers. Modifying route1.url will not modify route2.url. However, the way they've been initialized makes them both point to the same object so modifying that object can be done from either pointer.
The key to making this work is to create a new object for .url every time you create a new object. That can be done either in the constructor or in your case your .init() method:
Route = function (name, route_data, request_obj) {
this.url = {url: false, type: "get", defer: false};
this.init(name, route_data, request_obj);
}
Implied Lesson:
The lesson to take from this is that the object literal syntax is actually an object constructor. Not just a syntax.
// this:
{};
// is the same as this:
new Object();
So every time you see an object literal, in your mind you should be thinking new Object() then see if it makes sense to call it just once or do you need a new instance of it every time.
finalVariables() returns an object that contains data accessible by .dataName notation i.e. finalVariables().mainViewWindow0 returns the string stored for mainViewWindow0. I'm trying to access mainViewWindow0 using a dynamically created variable, but for obvious reasons this doesn't work so well with dot notation, but I don't know how to work around it. Help to be had for me?
Please ignore the poor coding practice of having a hard-coded number in there; I promise to get rid of it later
activePane = dot.id.substring(6); //gets dot # and sets it as active pane
var tempForPaneNumber = "mainViewWindow" + activePane + "";
document.getElementById("mainViewWindowContent").innerHTML = finalVariables().###this is where I want to use
the string from "tempForPaneNumber" to access ###
finalVariables[tempForPainNumber]()
Should do the trick if I understand correctly.
In Javascript you can access properties of an object either through the dot notation or through the use of brackets to specify the identifier for the property so myVar.foo is equivalent to myVar['foo']. Therefore, if I understand what you are asking correctly you want to use finalVariables()[tempForPaneNumber]()
I am using code lines like the following in order to fetch data from an intranet website:
util.setProp(obj, "firstNameOld", $(msg).find('#fname_a').text());
Now I have another function in the same file where I want to use the above again, resp. the value of that object - currently I am hard-coding this ('Test') for test purposes:
util.setProp(obj, "firstNameNew", 'Test');
How can I pass the value from the firstNameOld object in one function to the firstNameNew object in another function ? If a solution with global variables is better here than this would work as well.
Many thanks for any help with this, Tim.
I've never used the framework that includes util But I imagine that if there is a setProp() then there has to be a getProp() or something similar.
If so, you could do something like
util.setProp(obj, "firstNameNew", util.getProp(obj, "firstNameOld"));
This also relies on the assumption that you want to copy from two properties in the same object.
If not, then pass the desired source object in the getProp() call.
My guess is that functions (or properties) are called "firstNameOld" and "firstNameNew", so the first time you get it from selector, second time you want to do the same.
Try to use the local variable like that:
var text = $(msg).find('#fname_a').text();
//
util.setProp(obj, "firstNameOld", text);
//
util.setProp(obj, "firstNameNew", text);
I am using a Comet Push Engine called APE (Ajax Push Engine) and whenever I receive a realtime event I receive it in an javascript object called 'raw'.
So if for example if the raw object contains a 'location' value, I can print 'raw.location' and it will give me the value,
alert(raw.location);
So I have another object called currentSensor, which contains a value like this (in my example it would contain the string 'location'):
currentSensor.value
How do I programmatically use the currentSensor.value variable to access the 'raw' object? I have tried this:
var subsensor = currentSensor.sensorKey;
and then
alert(raw.subsensor);
But I keep getting undefined because the raw object doesn't contain a key called "subsensor" its actually "location". I hope this makes sense!
Thanks!
When using dot-notation, you use a literal property name. If you want to use a string, use square bracket notation.
foo.bar === foo['bar'];
Strings can be variables.
baz = 'bar';
foo.bar === foo[baz];
like this:
console.log(raw[currentSensor.value]);
Here you go:
alert(raw[subsensor]);
The dot syntax cannot help you when you need to access variable indexes. You need to use the array access method.
Note: The dot access method is just syntactic sugar and is not really needed in any place, but it is useful for code readability.
For your entertainment:
"1,2,3"["split"](",")["join"]("|")