javaScript reserved keywords - javascript

I am wondering how JavaScript's reserved keywords / functions are managed.
Example:
According to:
http://www.quackit.com/javascript/javascript_reserved_words.cfm
delete is a reserved keyword by JavaScript.
Then consider the following snippet for some context:
var cookieManager = {
get: function (name) {
// function contents ...
console.log("cookieManager.get() called");
return true;
},
set: function (name, value, days) {
// function contents ...
console.log("cookieManager.set() called");
return true;
},
delete: function (name) {
// function contents ...
console.log("cookieManager.delete() called");
return true;
}
};
This object has a delete property, yet the name of it is reserved by JavaScript so it should fail, right?
Yet when I execute cookieManager.delete(); in the webconsole of FireFox I get the following output, suggesting that it works fine:
[11:26:00.654] cookieManager.delete();
[11:26:00.656] cookieManager.delete() called
[11:26:00.657] true
If, however, you run the code in JsLint it says
Problem at line 12 character 5: Expected an identifier and instead saw 'delete' (a reserved word).
delete: function (name) {
Suggesting that this is a big no no approach and should be avoided.
So when should I take reserved keywords into consideration, as in this example it seems to work just like I want it to ( the delete keyword is in the context of the object cookieManager and thus causes no conflicts, hence it can be used ) or should I abide to the bible that is JsLint and rename anything that is a reserved keyword by javascript? In this context I could easily rename .delete() to .remove().

Actually this is allowed as per ECMAScript specification. The production rules (Section 11.1.5) for an object literal are:
ObjectLiteral :
{}
{PropertyNameAndValueList}
{PropertyNameAndValueList ,}
PropertyNameAndValueList :
PropertyAssignment
PropertyNameAndValueList , PropertyAssignment
PropertyAssignment :
PropertyName : AssignmentExpression
get PropertyName ( ){FunctionBody}
set PropertyName (PropertySetParameterList){FunctionBody}
PropertyName :
IdentifierName
StringLiteral
NumericLiteral
In your case, you use an IdentifierName as property name. Section 7.6.1 says:
A reserved word is an IdentifierName that cannot be used as an Identifier.
Note the difference: You cannot use a reserved keyword as Identifier, but as it is a valid IdentifierName you can use it as PropertyName.
Nevertheless, other (versions of) browsers might not tolerate this, so to be on the safe side, I would rename it.
Apart from possible problems with browsers, it might also confuse others who read your code and are not familiar with this rule.
FWIW, of course you can always use reserved keywords as strings:
var a = {'delete': 'foo'};
alert(a['delete']);

Related

Arguments before a colon

I'm trying to pass an argument to a function in Javascript. However, the argument column is being interpreted as a literal string as opposed to an argument to the function. This is due to the colon directly following the argument column:
update(column, selected) {
var cols = {...this.props.columns, column: selected}
this.props.dispatch(updateColumns({type: "UPDATE_COLUMNS", cols}))
}
I've tried using arguments[0] instead of column but then I am told arguments is a reserved word in strict mode. Any idea how I can get read this value as an argument as opposed to a string?
In modern JavaScript environments, object initializer syntax allows for expressions to be evaluated on the left side of the property initialization:
update(column, selected) {
var cols = {...this.props.columns, [column]: selected}
this.props.dispatch(updateColumns({type: "UPDATE_COLUMNS", cols}))
}
The square brackets mean that the expression inside should be evaluated, and the result should be used as the property name.
In older environments, you'd have to do it in a separate statement, but since you're already using spread syntax I'd guess you're not concerned with that.

How come if this is a reserved word in javascript, i'm still able to set it as a property?

Well this time, there was some interesting behavior that i observed, i would defeinitely like to know more.
var doStuff = function() {
this.this = function() {
console.log("I'm the other this");
}
this.this(); //Is this legal to be used ?
};
doStuff.call(null);
Output
I'm the other this
'The syntactic grammar defines Identifier as an IdentifierName that is not a ReservedWord (see 11.6.2)' However object properties can be accessed with MemberExpression . IdentifierName, and IdentifierNames aren't subject to that restriction.

JavaScript dash throws off ReferenceError

The following JavaScript...
if (eval('typeof admin_post_css_theme_dark-moon)=='function')) {/**/}
...triggers the following error message...
Error: ReferenceError: moon is not defined
The only thing I can really differentiate in this situation is that other themes don't have a dash in their names...
if (eval('typeof admin_post_css_theme_silver)=='function')) {/**/}
...doesn't trigger any errors.
So how is the dash between 'dark' and 'moon' triggering this error?
Edit: I wanted to take a moment and recommend that others who encounter this should adapt camelCase or something similar. In general I use a 'name' and a 'base' myself. The 'base' is the URL-friendly version of something that the 'name' includes URL unfriendly characters. In example 'My Example' and 'my-example' or 'my_example'.
http://en.wikipedia.org/wiki/CamelCase
JavaScript variable names can't contain dashes, object properties however can. For instance, something like this would work:
var themes = {
'admin_post_css_theme_dark-moon': function () {},
'admin_post_css_theme_silver': function () {}
};
if (typeof themes['admin_post_css_theme_dark-moon'] === 'function') {
/**/
}
Primarily because '-' is not a valid identifier in javascript, its the minus sign. Your eval in essence is trying to get the typeof the expression admin_post_css_theme_dark minus moon. Valid identifiers (i.e. variable, function or object names) in javascript are [A-Za-z0-9_$] but cannot start with a number (note this is a regex, and the hyphens in this context mean range i.e. a to z, just in case it was unclear)
My evolution to the question would be how would you have expected admin_post_css_theme_dark-moon to be defined, as you are expected it to be somehow/where in code, then in turn to test if it is a function.
As it would be absolutely impossible to do this
var admin_post_css_theme_dark-moon = function(){...};
//or
admin_post_css_theme_dark-moon = function(){...};
however it is possible to do this.
window['admin_post_css_theme_dark-moon'] = function(){...};
or preferably use your own object
var Themes = {};
Themes['admin_post_css_theme_dark-moon'] = function(){...};
//or
var Themes = {
'admin_post_css_theme_dark-moon' : function(){...};
}
As object properties if referenced by string index (i.e. between [] as a string) are not bound by the identifier rules.
then of course your eval would have to change also
something like
if (eval("typeof window['admin_post_css_theme_dark-moon']")=='function')) {/**/}
//or
if (eval("typeof Themes['admin_post_css_theme_dark-moon']")=='function')) {/**/}
NOTE the use of alternating " and ' so you don't have to escape
I changed...
eval('typeof '+my_object)=='function')
...to...
eval('typeof \''+my_object+'\'')=='function')
I didn't have the chance to edit this in so the question could be more concise. For those looking at just this answer check out the other answers from OJay and sabof as they are wholly relevant.

What's the difference when I enclose a method name inside a function in ' '? [duplicate]

This question already has answers here:
What is the difference between object keys with quotes and without quotes?
(5 answers)
Closed 9 years ago.
I have the following code:
var factory = {
query: function (selectedSubject) {
..
}
}
In Javascript is this the same as:
var factory = {
'query': function (selectedSubject) {
..
}
}
I have seen both used and I am not sure if there is any difference.
The standard requires a property name to be one of:
PropertyName :
IdentifierName
StringLiteral
NumericLiteral
that is, all of these are valid:
obj = {
"query": ....
'query': ....
query: ....
12e45: ....
}
Note that, contrary to the popular opinion, the standard does not require a name to be a valid identifier, only an "identifier name". This effectively means that you can use JS reserved words as property names:
x = {
if: 100,
function: 200,
}
console.log(x.if + x.function) // 300
Not that it's terribly useful in everyday programming, just a funny fact worth knowing about.
You can use both, but if there are spaces you can't use the first option. That's why there is a second option.
Valid JSON requires "" to surround property name of an anonymous object, but you can omit them if the property name is not reserved word or does't contain some special chars. Generally it is more safe to use "".

Javascript: access an object property whose name starts with a number

I'm creating a Javascript / jQuery application.
I need to process a JSON response that represents a HashMap, like this:
{
"accounts": {
"MediaFire": {
"provider": "MediaFire",
"usedStorage": "779680",
"totalStorage": "53687091200"
},
"4Sync": {
"provider": "4Sync",
"usedStorage": "620692",
"totalStorage": "16106127360"
}
}
}
I use a pasing function (which I can't control), which returns the parsed JSON response in an object result.
When I try to access the 4Sync like this:
var usedStorage = result.accounts.4Sync.usedStorage; //doesn't work
it doesn't work, I think it's because of the 4 at the beginning... The same operation with the other object works fine:
var usedStorage = result.accounts.MediaFire.usedStorage; //works
I know the result object contains the object 4Sync, but I can't access it. Here is a screenshot of Chrome's console:
Is there any workaround to solve this?
Use square brackets:
var usedStorage = result.accounts["4Sync"].usedStorage;
Property identifers can begin with a number, but member expressions with the . character will only allow valid variable identifiers (since anything else is ambiguous). To get around this, you can use the square bracket syntax, which is equivalent but allows the use of any string.
If you're interested, here is the grammar:
MemberExpression :
PrimaryExpression
FunctionExpression
MemberExpression [ Expression ]
MemberExpression . IdentifierName
Notice how square brackets can contain any expression, but the . can only be followed by an IdentifierName (basically, any valid identifier, plus reserved words in ES5).

Categories

Resources