I'm working on a dojo project and stumbled on code below:
format: function ( /*Date*/ value, /*locale.__FormatOptions*/ constraints) {
....
},
"parse": function ( /*String*/ value, /*locale.__FormatOptions*/ constraints) {
.....
},
As you can see parse method name is a string. I haven't seen something like this before. Is there any reason for doing this?
Link to original file.
According to JavaScript / ECMAScript standard, object property (or functions) identifiers (as used before the colon : in your example) can be any valid identifier (i.e. like the format without quotes), any string (like "parse") or even any number.
Using "parse" in that case is strictly equivalent as using parse, but that would have been different in the case for example of "parse that value", which is a valid string identifier for an object property, even though it has spaces!
Then you can use either myObject.parse or myObject["parse"] to access your property, whereas in my last example you have no choice but using myObject["parse that value"] to access it.
I think we should also mention a specific case where using quotes for object keys is different from without quotes: if you were to use Google Closure minifier in ADVANCED_OPTIMIZATIONS mode, it would replace any non-quoted identifier to try and save space, whereas it would leave intact quoted identifiers, as Google team took this as the indicator that you will try to access it later on with the square brackets method and string, or if you check the actual key name like this:
for (var i in myObject) {
if (i === "parse") { // if i is replaced by the minifier, you will never execute the block below
// do something...
}
}
This specificity which forces you to use quoted identifiers sometimes (but not always, if you do not need to keep the original name) is one of the reasons that push people not using this advanced optimizations mode.
I don't see any reason for using extra quotes.
JSON requires it, but your object literal is not JSON. ES3 required this for keywords, but parse never was a keyword.
In this particular case there is no reason to do that, but I've faced scenarios where I needed to use quotes to define elements. For example:
var httpHeadersToAdd= {
'User-Agent': 'whatever',
Date: new Date()
};
With no quotes the interpreter understands that your are trying to do a subtract operation with variables User and Agent and throws a syntax error SyntaxError: Unexpected token -. Same can be made with functions, and then you have to call them with brackets:
var obj= {
'my-function': function (){}
}
obj['my-function']();
Going back to the code you linked, maybe someone wrote that in a JSON-ish way because that's how JSON strings looks like (double quotes are mandatory in JSON, single quotes don't work)
Related
I have a text input.
I want the user to be able to fill out a value in that text input like some of these examples:
results[0].address_components[0].long_name
results[0].formatted_address
fo.o[0].bar (where fo.o is a single key)
etc. (pretty much literally anything)
Then I want to take that value and use it as a key on some parsed JSON. So like...
$.parseJSON('data.json').results[0].address_components[0].long_name would return something like San Francisco.
How can I do this?
If I save the input value as a variable, say selector, and then try $.parseJSON('data.json')[selector] it just comes back undefined.
If I try to regex the selector and convert all instances of [ into . and remove all ] and split at . then reduce, then selectors like fo.o (one key) will break...
Thanks in advance!
You should generally set the results of parseJSON to a variable, rather than parse it every time you access it. parseJSON is generally going to go down to C code (depending on the environment), but it will still be really inefficient to call it over and over.
var res = $.parseJSON('data.json');
From there, you can access it like you would any other JavaScript object:
res.results, which is identical to res["results"] (which, in your case appears to be some kind of array).
A string key with special characters (., -, and pretty much anything non a-zA-Z0-9) is always accessed via the second form: res["fo.o"].
Note that this chains, so you can access res["fo.o"]["bar"] exactly as you'd address res["fo.o"].bar.
I would recommend using a JavaScript library like lodash for this (if this is feasible in your project, otherwise looking at its implementation might help):
It provides a large set of utility functions. The get function does exactly what you are looking for, namely it resolves a path on an object.
Sample code (assuming _ is your lodash reference):
var path = 'results[0].address_components[0].long_name'; // the user input
var data = $.parse('data.json');
var result = _.get(data, path); // resolves the path on the data object
As for the fo.o property name, I doubt there would be an easy solution, as this essentially makes your syntax ambiguous. How would you distinguish between a property fo.o and fo?
use eval. You would put everything as a string. So just concatenate strings based on the input. Then eval it. for example:
var str = "$.parseJSON('data.json').results[0].address_components[0].long_name";
and then eval it at runtime.
var result = eval(str);
This question already has answers here:
What is the purpose of the dollar sign in JavaScript?
(12 answers)
Closed 2 years ago.
I quite often see JavaScript with variables that start with a dollar sign. When/why would you choose to prefix a variable in this way?
(I'm not asking about $('p.foo') syntax that you see in jQuery and others, but normal variables like $name and $order)
Very common use in jQuery is to distinguish jQuery objects stored in variables from other variables.
For example, I would define:
var $email = $("#email"); // refers to the jQuery object representation of the dom object
var email_field = $("#email").get(0); // refers to the dom object itself
I find this to be very helpful in writing jQuery code and makes it easy to see jQuery objects which have a different set of properties.
In the 1st, 2nd, and 3rd Edition of ECMAScript, using $-prefixed variable names was explicitly discouraged by the spec except in the context of autogenerated code:
The dollar sign ($) and the underscore (_) are permitted anywhere in an identifier. The dollar sign is intended for use only in mechanically generated code.
However, in the next version (the 5th Edition, which is current), this restriction was dropped, and the above passage replaced with
The dollar sign ($) and the underscore (_) are permitted anywhere in an IdentifierName.
As such, the $ sign may now be used freely in variable names. Certain frameworks and libraries have their own conventions on the meaning of the symbol, noted in other answers here.
As others have mentioned the dollar sign is intended to be used by mechanically generated code. However, that convention has been broken by some wildly popular JavaScript libraries. JQuery, Prototype and MS AJAX (AKA Atlas) all use this character in their identifiers (or as an entire identifier).
In short you can use the $ whenever you want. (The interpreter won't complain.) The question is when do you want to use it?
I personally do not use it, but I think its use is valid. I think MS AJAX uses it to signify that a function is an alias for some more verbose call.
For example:
var $get = function(id) { return document.getElementById(id); }
That seems like a reasonable convention.
I was the person who originated this convention back in 2006 and promoted it on the early jQuery mailing list, so let me share some of the history and motivation around it.
The accepted answer gives this example:
var $email = $("#email"); // refers to the jQuery object representation of the dom object
var email_field = $("#email").get(0); // refers to the dom object itself
But that doesn't really illustrate it well. Even without the $, we would still have two different variable names here, email and email_field. That's plenty good right there. Why would we need to throw a $ into one of the names when we already have two different names?
Actually, I wouldn't have used email_field here for two reasons: names_with_underscores are not idiomatic JavaScript, and field doesn't really make sense for a DOM element. But I did follow the same idea.
I tried a few different things, among them something very similar to the example:
var email = $("#email"), emailElement = $("#email")[0];
// Now email is a jQuery object and emailElement is the first/only DOM element in it
(Of course a jQuery object can have more than one DOM element, but the code I was working on had a lot of id selectors, so in those cases there was a 1:1 correspondence.)
I had another case where a function received a DOM element as a parameter and also needed a jQuery object for it:
// email is a DOM element passed into this function
function doSomethingWithEmail( email ) {
var emailJQ = $(email);
// Now email is the DOM element and emailJQ is a jQuery object for it
}
Well that's a little confusing! In one of my bits of code, email is the jQuery object and emailElement is the DOM element, but in the other, email is the DOM element and emailJQ is the jQuery object.
There was no consistency and I kept mixing them up. Plus it was a bit of a nuisance to keep having to make up two different names for the same thing: one for the jQuery object and another for the matching DOM element. Besides email, emailElement, and emailJQ, I kept trying other variations too.
Then I noticed a common pattern:
var email = $("#email");
var emailJQ = $(email);
Since JavaScript treats $ as simply another letter for names, and since I always got a jQuery object back from a $(whatever) call, the pattern finally dawned on me. I could take a $(...) call and just remove some characters, and it would come up with a pretty nice name:
$("#email")
$(email)
Strikeout isn't perfect, but you may get the idea: with some characters deleted, both of those lines end up looking like:
$email
That's when I realized I didn't need to make up a convention like emailElement or emailJQ. There was already a nice convention staring at me: take some characters out of a $(whatever) call and it turns into $whatever.
var $email = $("#email"), email = $email[0];
// $email is the jQuery object and email is the DOM object
and:
// email is a DOM element passed into this function
function doSomethingWithEmail( email ) {
var $email = $(email);
// $email is the jQuery object and email is the DOM object
// Same names as in the code above. Yay!
}
So I didn't have to make up two different names all the time but could just use the same name with or without a $ prefix. And the $ prefix was a nice reminder that I was dealing with a jQuery object:
$('#email').click( ... );
or:
var $email = $('#email');
// Maybe do some other stuff with $email here
$email.click( ... );
In the context of AngularJS, the $ prefix is used only for identifiers in the framework's code. Users of the framework are instructed not to use it in their own identifiers:
Angular Namespaces $ and $$
To prevent accidental name collisions with your code, Angular prefixes names of public objects with $ and names of private objects with $$. Please do not use the $ or $$ prefix in your code.
Source: https://docs.angularjs.org/api
Stevo is right, the meaning and usage of the dollar script sign (in Javascript and the jQuery platform, but not in PHP) is completely semantic. $ is a character that can be used as part of an identifier name. In addition, the dollar sign is perhaps not the most "weird" thing you can encounter in Javascript. Here are some examples of valid identifier names:
var _ = function() { alert("hello from _"); }
var \u0024 = function() { alert("hello from $ defined as u0024"); }
var Ø = function() { alert("hello from Ø"); }
var $$$$$ = function() { alert("hello from $$$$$"); }
All of the examples above will work.
Try them.
The $ character has no special meaning to the JavaScript engine. It's just another valid character in a variable name like a-z, A-Z, _, 0-9, etc...
Since _ at the beginning of a variable name is often used to indicate a private variable (or at least one intended to remain private), I find $ convenient for adding in front of my own brief aliases to generic code libraries.
For example, when using jQuery, I prefer to use the variable $J (instead of just $) and use $P when using php.js, etc.
The prefix makes it visually distinct from other variables such as my own static variables, cluing me into the fact that the code is part of some library or other, and is less likely to conflict or confuse others once they know the convention.
It also doesn't clutter the code (or require extra typing) as does a fully specified name repeated for each library call.
I like to think of it as being similar to what modifier keys do for expanding the possibilities of single keys.
But this is just my own convention.
${varname} is just a naming convention jQuery developers use to distinguish variables that are holding jQuery elements.
Plain {varname} is used to store general stuffs like texts and strings.
${varname} holds elements returned from jQuery.
You can use plain {varname} to store jQuery elements as well, but as I said in the beginning this distinguishes it from the plain variables and makes it much easier to understand (imagine confusing it for a plain variable and searching all over to understand what it holds).
For example :
var $blah = $(this).parents('.blahblah');
Here, blah is storing a returned jQuery element.
So, when someone else see the $blah in the code, they'll understand it's not just a string or a number, it's a jQuery element.
As I have experienced for the last 4 years, it will allow some one to easily identify whether the variable pointing a value/object or a jQuery wrapped DOM element
Ex:
var name = 'jQuery';
var lib = {name:'jQuery',version:1.6};
var $dataDiv = $('#myDataDiv');
in the above example when I see the variable "$dataDiv" i can easily say that this variable pointing to a jQuery wrapped DOM element (in this case it is div). and also I can call all the jQuery methods with out wrapping the object again like $dataDiv.append(), $dataDiv.html(), $dataDiv.find() instead of $($dataDiv).append().
Hope it may helped.
so finally want to say that it will be a good practice to follow this but not mandatory.
While you can simply use it to prefix your identifiers, it's supposed to be used for generated code, such as replacement tokens in a template, for example.
Angular uses is for properties generated by the framework. Guess, they are going by the (now defunct) hint provided by the ECMA-262 3.0.
$ is used to DISTINGUISH between common variables and jquery variables in case of normal variables.
let you place a order in FLIPKART then if the order is a variable showing you the string output then it is named simple as "order" but if we click on place order then an object is returned that object will be denoted by $ as "$order" so that the programmer may able to snip out the javascript variables and jquery variables in the entire code.
If you see the dollar sign ($) or double dollar sign ($$), and are curious as to what this means in the Prototype framework, here is your answer:
$$('div');
// -> all DIVs in the document. Same as document.getElementsByTagName('div')!
$$('#contents');
// -> same as $('contents'), only it returns an array anyway (even though IDs must be unique within a document).
$$('li.faux');
// -> all LI elements with class 'faux'
Source:
http://www.prototypejs.org/api/utility/dollar-dollar
The reason I sometimes use php name-conventions with javascript variables:
When doing input validation, I want to run the exact same algorithms both client-side,
and server-side. I really want the two side of code to look as similar as possible, to simplify maintenance. Using dollar signs in variable names makes this easier.
(Also, some judicious helper functions help make the code look similar, e.g. wrapping input-value-lookups, non-OO versions of strlen,substr, etc. It still requires some manual tweaking though.)
A valid JavaScript identifier shuold must start with a letter,
underscore (_), or dollar sign ($);
subsequent characters can also
be digits (0-9). Because JavaScript is case sensitive,
letters
include the characters "A" through "Z" (uppercase) and the
characters "a" through "z" (lowercase).
Details:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#Variables
I was expecting JavaScript to reject objects with duplicated properties as invalid but it accepts them in some cases.
{"a":4,"a":5} results in an SyntaxError at least in Firefox and Chrome which seems obvious due to the property a being defined twice.
However ({"a":4,"a":5}) evaluates just fine and results in an object {"a":5} in both Firefox and Chrome.
Why is the expression with the parenthesis accepted?
Summing up the responses: The first example is simply not the construction of an object but a block of labeled statements. Duplicated properities in objects are perfectly valid in which case the last definition wins.
Thanks a lot for your answers!
It is perfectly legal in ECMAScript 3 to declare duplicate properties in an object literal; the SyntaxError you get probably comes from the fact that you used an object literal as a statement, which is not possible due to the confusion with block statements ({ doSomething(); }).
If you want this to be reported as an error, you may want to switch to ECMAScript 5's strict mode: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/Strict_mode.
What you state has no problem if you assign it to a variable, if you don't however, you get the error you mention. Which makes all the difference from a syntax point of view.
When you wrap any structure in parens you are causing that syntax to be evaluated as an expression, the result of which is stored as a temporary variable. The error I get when not doing so in Firefox is unexpected label or invalid label, so it seems without assignment, or parens, this object construction is not treated as an object construction - instead it is treated as a block with multiple label statements that are defined illegally:
{
a: function(){
alert('a');
},
b: function(){
alert('b');
}
}
The above should be totally acceptable as an object, however you get a similar error if you evaluate it without assinging it to some form of variable, or evaluating it with parens. Put simply the duplication of the attribute name is not causing the error :)
Basically imagine your first example, but like this:
function (){
"a": 4,
"b": 5
}
That is roughly how these browsers are treating it, which is now obviously illegal javascript syntax... whereas it wasn't so obvious before.
In the first notation (parentheses-less) the javascript syntax is ambiguous. From ecmascript specification:
An ExpressionStatement cannot start with an opening curly brace
because that might make it ambiguous with a Block.
A block basically evaluates all the statements inside, equivalent to evaluating "a":4,"a":5 which is not valid JS and, in fact, returns the same SyntaxError Unexpected token :
Wrapping that code in parentheses (or, rather, a grouping operator) removes that ambiguity since an assignment expression cannot be followed by a block statement:
var test = {"a":"a","a":"b"}; //test.a === "b"
Furthermore this ambiguity can be removed by any operator or expression that cannot be used with a block statement. A practical scenario hardly comes to mind, maybe if you wanted to return an object literal as part of a conditional operator?
//this *could* come out of a JS minifier:
return x ? (foo(),{"a":"b"}) : (bar(), {"b":"a"});
Why should it not be accepted? You're simply overwriting the values. I think it's rather a feature, than an error. And it works fine for me on various browsers: http://jsbin.com/oculon/1/edit
It's like writing
var a;
a = 4;
a = 5;
alert(a);
it's not Error you just overwrite value with another
I'm guessing (though not certain) that this evaluates as an error because of the difference between the way Firefox and Chrome's JS parsers treat statements and expressions. So because it's wrapped in parentheses the second time, it's considered an expression. Since it's looking for less information in an expression, it can ignore erroneous values. You'll see that if you do...
var a = {'a': 5, 'a': 4};
console.log(a);
It works fine! And also notice that here it's in the right hand side of the statement, giving a hint that it's an expression.
I've been using the Youtube json api for making a new mash-up.
Somewhere in the response you can find the following:
{
"player":
{
"default":"http://www.youtube.com/watch?v\u003deH5Iysm417U"
}
}
I've always learned not to use any words mentioned in the reserved words section of the ECMAScript standard as identifiers. So as far as I know it's not allowed to use the name "default" as a property name. Why is Youtube doing this?
player.default
To be honest, the above code works fine in a browser. But I had to change it to the code beneath in order to have no compile errors when using the Google closure compiler.
player["default"]
It just feels wrong.
The most important question here is, can I do anything about it?
An Identifier is not the same as a PropertyName.
PropertyName need only not consist of reserved words when declared without quotes. When declared with quotes, then all strings are valid, even " ".
Here is the list of the valid productions:
PropertyName :
Identifier
StringLiteral
NumericLiteral
http://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%203rd%20edition,%20December%201999.pdf, 11.1.15
You cannot change the response from Youtube, and allthough there is nothing wrong with player.default, you will simply need to use the [] accessor if you want to avoid this error in the closure compiler.
But really, this is a bug with the compiler, not the javascript.
The compiler might be flagging this up due to cross-browser compatibility issues.
I hit the same thing recently with both default and extends when creating a template library which uses code instead of parsing text. The code worked just fine, but the Closure Compiler complained about those keywords when used as properties... then I tried it in IE:
>>> var o = {default: 'test'}
SyntaxError: Expected identifier, string or number
>>> var o = {'default': 'test'}
>>> o.default
SyntaxError: Expected identifier
Here is the problem string:
$.ajax(......
,success:function(msg){
var obj = eval('['+msg.d+']');
},
....
}
msg.d contains something like:
new Person(2, 'Name Surname','This is just string came from Par'is at Sat'urday');
How can pass the javascript problem ?
If the string really is as you've quoted it, it has a syntax error and will not work (it has an errant ' inside the word "Saturday"). Otherwise, though, change the brackets ([ and ]) in your eval call to parentheses (( and )):
var obj = eval('('+msg.d+')');
However, it should almost never actually be necessary to do this (or indeed to use eval at all). It's almost always possible, and desirable, to refactor slightly and avoid it.
If that's a literal quote from your code, see also dvhh's answer below, your function argument name (msg.d) is invalid.
Using eval in this scenario is actual quite dangerous. You really ought to be using XML or JSON. (That's why they call it AJAX.)
the function argument should be a valid javascript identifier
try changing msg.d to msg_d for example
You may need to escape your string, because this example works fine:
function MyObject(myvar){
this.hello = function(){
alert('myvar= ' + myvar);
};
}
var obj1 = new MyObject('hello');
obj1.hello();
var obj2 = eval("new MyObject('world')");
obj2.hello();
(Edit: By the way, I assume msg.d is a typo due to editing the snipplet before posting on StackOverflow ?)
I would avoid using eval() for security reasons. If a user can get malicious code into the database, there's a chance it could end up in this eval expression, wreaking havoc for anybody who visits this page.
Instead of using eval, I'd recommending returning JSON from the AJAX request. You can then easily parse the values and build a new Person object with that data.