Viable JavaScript Variable Names - javascript

This is a two part question: General, and Specific.
For the general: I often find myself wondering what constitutes a viable variable name in JavaScript? I know there are certain 'words' that can not be used as variables in JavaScript; But I have yet to come across either a list of non-viable variable names, or a rule to apply when creating a variable name. I usually err on the side of caution and use obscure names if I am unsure.
It would be nice to know, with certainty, what can be used as a JavaScript variable, and what can not be used.
Any advice?
For the specific: I am wondering if I can use href as a variable name in my JavaScript? Is it viable, or is it reserved?
Afterthought: Perhaps I can extend this question to encompass JavaScript function names as well. What names are viable, and which are reserved? If the two questions are related, I will edit to ask both.
Note: I am not asking which characters can be used in a JavaScript variable; That question is already answered here.

Uhm, actually, you can use any kind of name as a variable name.
Instead of referring to the variable by name, refer to it by array index, since all object properties in JS can be accessed by index*, as well as the fact that global variables are simply properties of the window object.
*a string index can contain literally any kind of character sequence
So the question in turn might be more on the lines of "should I use reserved words as variable names?"
Common sense would say you shouldn't, except when such a name is actually related to the construct and you can't find a suitable replacement.
window['function'] = 2;
window['if'] = 4;
window['var'] = 8;
alert(window['function'] + window['if'] + window['var']);
Warning!
Reserved words are different from native functionality.
Although in many cases you can use names used as reserved keywords as variables, native functionality can actually be overwritten.
For instance Mr Sarris above mentioned Node, (which is a native function not a reserved keyword), you can actually overwrite it by doing window['Node'] = myNewThing;. This has been used in some cases to achieve "wrapper" or "hotfix" functionality, but it is not guaranteed to work in a cross-browser manner (eg; MSIE's console object).

You can find lists of reserved words in JavaScript.
href is certainly fine as a variable name because href is an attribute of an a tag and in no way conflicts with JavaScript naming.
If you are ever in doubt as to whether or not a variable is already in use you can always open the developer tools (F12 in most browsers), go to the console, and type in the name. In this case you'll get:
> href
x ReferenceError: href is not defined
Nothing is using it, so it is yours to use without problem.
Just for kicks if you did enter a reserved word it would look like:
> finally
x SyntaxError: Unexpected token finally
Or if it was a native but already taken word it might look like:
> Node
function Node() { [native code] }
(Node is already defined, and its a native function)

Every programming language has a list of reserved words.
These reserved words consist of the parts that constitute that programming language.
For JavaScript, things like for or function or if are reserved words, since these have special meaning in the language itself. As a rule of thumb you cannot re-use words as identifiers (names) that already have a meaning in that particular language.
The official language specification is a good place to look that up. For JavaScript see the ECMAScript specification, section 7.6.1 (section 7.6. clarifies the other rules that apply to identifier naming).
Your question whether href is okay to use in JS is easily answered by looking there.

rules for variable declaration (on codelifter)
href is ok to use

Related

Referring to element without document [duplicate]

This question already has answers here:
Do DOM tree elements with IDs become global properties?
(5 answers)
Closed 5 years ago.
Just today after a couple of years of javascript programming I came across something that left me startled. Browsers create objects for every element with an id. The name of the object will match the id.
So if you have:
<div id ="box"></div>
You can do:
alert(box); //[object HTMLDivElement]
Without first assigning anything to that variable. See the demo.
This for some reason seems to be in the standards even though it can break the code in some cases. There is an open bug to end this behavior but I'm more interested in getting rid of it now.
Do you guys know if there is a way to disable this (strict mode maybe)? Am I giving this too much importance? Because it certainly seems like a bad idea. (It was introduced by IE to give you a hint).
Update: It seems FF only does this in quirks mode. Other browsers like IE6+ and Chrome do it right off the bat.
ECMAScript 5 strict should help with this as you cannot use undeclared variables. I'm not sure which browsers currently support strict mode but I know Firefox 4 does.
The HTML spec you linked mentions a proposal to reduce pollution of the global scope by limiting this behavior to quirks-only.
I don't know if this feature is in the original spec but I do expect it to be removed, prohibited or otherwise nullified in subsequent versions of ECMAScript. ES6 will be based on ES5 strict.
JavaScript has many features that make it easier to use for beginners and novices, I suspect this is one such feature. If you're a professional and you want quality code use "use strict"; and always JSLint your code. If you use these guidelines this feature should never bother you.
Here is a useful video about ES5 courtesy of YUI Theater (it's already 2 years old though, but still relevant currently as there is no ES6 yet).
I don't think this is much of a big deal. It seems messy especially to those of us who think about global namespace pollution and conflicts, but in practice it doesn't really cause a problem.
If you declare your own global variable, it will just override anything the browser created for you so there's not really any conflict. The only place I could see it potentially causing a problem is if you were testing for the existence of a global declaration and an "auto" global based on an object ID got in the way of that and confused you.
In practice, I've never seen this to be a problem. But, I'd agree it seems like something they should get rid of or allow you to turn off.
Yes most browsers do this but then again like you said some don't (firefox) so don't count on it. It's also easy to overwrite these variables in js, I can imagine something like container might be overwritten right of the bat by someone using that variable without declaring it first.
There is no way to turn this of in chrome afaik but even then it might be a hassle to figure this out and fix it for all browsers.
Don't give it too much importance, but beware of it. This is one of those reasons why you would evade the global scope for variables.
For the sake of completion, these browsers definitly do it by default: Chrome, IE9 & compat, Opera
Update: Future versions of ECMAScript might include an option of some sort since yes discussion is going on, but that will not fix the 'problem' in older browsers.
I don't think there's a way to disable it, but you don't need to put much importance to it. If you are afraid of unpredictable bugs, you could avoid them by using JSHint or JSLint. They will help you avoid mistakes. For example, they will warn you if you use an undeclared variable.
The problem here is that the global scope has objects defined in it at runtime by the browser, and you would like to prevent these definitions from interfering with your code. I'm not aware of a way to turn off this behaviour, but I do have two workarounds for you:
1) As suggested in the article you linked to, you can work around this by ensuring that you define each variable before you use it. I would achieve this by running my code through JSLint, which warns about this sort of thing (in addition to a bunch of other common errors).
2) However, since it's possible to forget to run your code through JSLint, you might prefer a step in the tool chain that you can't forget. In that case, have a look at CoffeeScript - it's a langauge very similar to javascript that you compile into javascript before use, and it will insert the correct var definitions for you. In fact, I suspect that you can't write code that relies on the automatic element variable creation using CoffeeScript.
This is what I've been able to come up with to remove global variables that are automatically created for DOM objects with an ID value:
function clearElementGlobals() {
function clearItem(iden, item) {
if (iden && window[iden] && (window[iden] === item)) {
window[iden] = undefined;
}
}
var list = document.getElementsByTagName("*");
for (var i = 0, len = list.length; i < len; i++) {
var item = list[i];
clearItem(item.id, item);
clearItem(item.name, item);
}
}
This gets a list of all objects in the page. It loops through looking for ones with an id value and when there's an id value and a global variable exists for it and that global variable points to that DOM object, that global variable is set to undefined. As it turns out browsers also do this same auto-global for some types of tags with a name attribute (like form elements) so we clear those too.
Of course, this code can't know whether your own code makes a global variable with the same name as the id so it would obviously be best to either not do that in your own code or call this function before your global variables are initialized.
Unfortunately, you cannot delete global variables in javascript so setting it to undefined is about the best that can be done.
FYI, I tried doing this the other way around where you enumerate global variables looking for variables that are an instance of HTMLElement and that have a name that matches the id of the element they point to, but I couldn't find a reliable way to enumerate global variables. In Chrome, you can't enumerate them on the window object even though you can access them through the window object. So, I had to go the other way around by getting all DOM objects with an id and looking for globals that match them.
FYI, you asked about strict mode in your question. strict mode only applies to a given scope of code so there would not be any way to cause it to affect the way the global namespace was set up. To affect something like this, it would have to be something at the document level before the document was parsed like a DOCTYPE option or something like that.
Caveats with this function.
Run it before you create any of your own globals or don't create any of your own globals with the same name as the ID or name attribute that also point to that DOM object.
This is a one-time shot, not continuous. If you dynamically create new DOM objects, you would have to rerun this function to clear any new globals that might have been made from the new DOM objects.
The globals are set to undefined which is slightly different than if they were never there in the first place. I can't think of a programming case where it would really matter, but it isn't identical. Unfortunately, you can't delete global variables.

jQuery why can I select the id using dot notation [duplicate]

This question already has answers here:
Do DOM tree elements with IDs become global properties?
(5 answers)
Closed 5 years ago.
Just today after a couple of years of javascript programming I came across something that left me startled. Browsers create objects for every element with an id. The name of the object will match the id.
So if you have:
<div id ="box"></div>
You can do:
alert(box); //[object HTMLDivElement]
Without first assigning anything to that variable. See the demo.
This for some reason seems to be in the standards even though it can break the code in some cases. There is an open bug to end this behavior but I'm more interested in getting rid of it now.
Do you guys know if there is a way to disable this (strict mode maybe)? Am I giving this too much importance? Because it certainly seems like a bad idea. (It was introduced by IE to give you a hint).
Update: It seems FF only does this in quirks mode. Other browsers like IE6+ and Chrome do it right off the bat.
ECMAScript 5 strict should help with this as you cannot use undeclared variables. I'm not sure which browsers currently support strict mode but I know Firefox 4 does.
The HTML spec you linked mentions a proposal to reduce pollution of the global scope by limiting this behavior to quirks-only.
I don't know if this feature is in the original spec but I do expect it to be removed, prohibited or otherwise nullified in subsequent versions of ECMAScript. ES6 will be based on ES5 strict.
JavaScript has many features that make it easier to use for beginners and novices, I suspect this is one such feature. If you're a professional and you want quality code use "use strict"; and always JSLint your code. If you use these guidelines this feature should never bother you.
Here is a useful video about ES5 courtesy of YUI Theater (it's already 2 years old though, but still relevant currently as there is no ES6 yet).
I don't think this is much of a big deal. It seems messy especially to those of us who think about global namespace pollution and conflicts, but in practice it doesn't really cause a problem.
If you declare your own global variable, it will just override anything the browser created for you so there's not really any conflict. The only place I could see it potentially causing a problem is if you were testing for the existence of a global declaration and an "auto" global based on an object ID got in the way of that and confused you.
In practice, I've never seen this to be a problem. But, I'd agree it seems like something they should get rid of or allow you to turn off.
Yes most browsers do this but then again like you said some don't (firefox) so don't count on it. It's also easy to overwrite these variables in js, I can imagine something like container might be overwritten right of the bat by someone using that variable without declaring it first.
There is no way to turn this of in chrome afaik but even then it might be a hassle to figure this out and fix it for all browsers.
Don't give it too much importance, but beware of it. This is one of those reasons why you would evade the global scope for variables.
For the sake of completion, these browsers definitly do it by default: Chrome, IE9 & compat, Opera
Update: Future versions of ECMAScript might include an option of some sort since yes discussion is going on, but that will not fix the 'problem' in older browsers.
I don't think there's a way to disable it, but you don't need to put much importance to it. If you are afraid of unpredictable bugs, you could avoid them by using JSHint or JSLint. They will help you avoid mistakes. For example, they will warn you if you use an undeclared variable.
The problem here is that the global scope has objects defined in it at runtime by the browser, and you would like to prevent these definitions from interfering with your code. I'm not aware of a way to turn off this behaviour, but I do have two workarounds for you:
1) As suggested in the article you linked to, you can work around this by ensuring that you define each variable before you use it. I would achieve this by running my code through JSLint, which warns about this sort of thing (in addition to a bunch of other common errors).
2) However, since it's possible to forget to run your code through JSLint, you might prefer a step in the tool chain that you can't forget. In that case, have a look at CoffeeScript - it's a langauge very similar to javascript that you compile into javascript before use, and it will insert the correct var definitions for you. In fact, I suspect that you can't write code that relies on the automatic element variable creation using CoffeeScript.
This is what I've been able to come up with to remove global variables that are automatically created for DOM objects with an ID value:
function clearElementGlobals() {
function clearItem(iden, item) {
if (iden && window[iden] && (window[iden] === item)) {
window[iden] = undefined;
}
}
var list = document.getElementsByTagName("*");
for (var i = 0, len = list.length; i < len; i++) {
var item = list[i];
clearItem(item.id, item);
clearItem(item.name, item);
}
}
This gets a list of all objects in the page. It loops through looking for ones with an id value and when there's an id value and a global variable exists for it and that global variable points to that DOM object, that global variable is set to undefined. As it turns out browsers also do this same auto-global for some types of tags with a name attribute (like form elements) so we clear those too.
Of course, this code can't know whether your own code makes a global variable with the same name as the id so it would obviously be best to either not do that in your own code or call this function before your global variables are initialized.
Unfortunately, you cannot delete global variables in javascript so setting it to undefined is about the best that can be done.
FYI, I tried doing this the other way around where you enumerate global variables looking for variables that are an instance of HTMLElement and that have a name that matches the id of the element they point to, but I couldn't find a reliable way to enumerate global variables. In Chrome, you can't enumerate them on the window object even though you can access them through the window object. So, I had to go the other way around by getting all DOM objects with an id and looking for globals that match them.
FYI, you asked about strict mode in your question. strict mode only applies to a given scope of code so there would not be any way to cause it to affect the way the global namespace was set up. To affect something like this, it would have to be something at the document level before the document was parsed like a DOCTYPE option or something like that.
Caveats with this function.
Run it before you create any of your own globals or don't create any of your own globals with the same name as the ID or name attribute that also point to that DOM object.
This is a one-time shot, not continuous. If you dynamically create new DOM objects, you would have to rerun this function to clear any new globals that might have been made from the new DOM objects.
The globals are set to undefined which is slightly different than if they were never there in the first place. I can't think of a programming case where it would really matter, but it isn't identical. Unfortunately, you can't delete global variables.

$ sign in JavaScript function

I've found some weird for me function in the project that I'm currently working on:
Building.Widget.ClientIdV2 = function Building$Widget$ClientIdV2() {
...
What does $ mean here and what does the "name" of this function mean (Building$Widget$ClientIdV2) ? I've seen also ... = function () { code so far..
Thank you.
The dollar sign has no special significance. It is just a character you can use in an identifier.
The name of the function can be used to refer to the function from inside its own scope (which can be useful for recursive functions) and will appear in useful places like stack traces.
$ is just another character you can use in an identifier, it has no intrinsic special meaning. It could be Q or _ just as easily.
In that particular example, the original author is naming the function in a way that they can readily see that it's the ClientIdV2 function on the Widget object on the Building object. But that's just the author's convention. That's useful for looking at call stacks and such.
It looks like it's someones naming convention. You can preety much put anything that you want in Javascript variable names. You should try finding general naming conventions in Javascript in case that you're interested in that(it will make your work with other developers much easier).
For example, some people like to put the $ before jQuery variables, implying that they can chain functions on that selection.
In Javascript it's completely valid to use $ in names, just like letters or underscores, so syntactically it means nothing special. Thought it's frequently used to give extra semantic meaning to names, for eg. it may indicate that a variable is special to a system (internal variable, global, etc.). In your case I believe $ indicates object hierarchy. The use of $ is just conventional.

Symbol.for(string) in ECMAScript 6

It took me a while but I finally figured out what the purpose of symbols in ECMAScript 6 is: avoiding name collision when attaching properties to shared objects - HTML elements e.g. (In case you're stuck on the same question, I recommend this article.)
But then I stumbled upon Symbol.for(). Apparently ECMAScript 6 will maintain a global symbol registry which you can query with this function by providing the symbol description. Come again? If I use symbols to avoid name collisions, why would I want code other than my own to use them? (*) And how would I avoid name collisions in that global registry? Sharing of symbols seems to completely subvert the concept and a global registry doubly so.
(*) Yes, I know symbols aren't truly private, but that's besides the point.
If you don't want your symbols to be available in GlobalSymbolRegistry, just don't use Symbol.for.
Only use it if you want to allow other codes to use your symbol.
In the following example, I create a symbol to store data in DOM elements. And I may want every other code (e.g. internal raw uncompiled handlers) to read that data. So I make the symbol globally available.
var sym = Symbol.for('storeDataInDOM');
document.querySelector('button')[sym] = 'Hello, world!';
<button onclick="alert(this[Symbol.for('storeDataInDOM')])">Click me</button>
It's like creating global variables: should be avoided in general, but has its advantages. But with symbols instead of strings.
If I use symbols to avoid name collisions, why would I want code other than my own to use them?
That's not the only use case of symbols. The two most important other ones are:
they don't collide with string-keyed properties
they are not enumerated by the usual mechanics
Sharing of symbols seems to completely subvert the concept and a global registry doubly so.
Not necessarily. Right from that article you read: "The registry is useful when multiple web pages, or multiple modules within the same web page, need to share a symbol." The best example for these are the intrinsic symbols - they guarantee interoperability across realms, that's why the global symbol registry is more global than your global scope.
For example you might have a library that is loaded in a web page, an iframe and a web worker. If you share data between those environments (realms), all of the three instances of your library would want to use the same symbol.
There also is a real need interoperability between different libraries, which might not even know about each other. Good examples are transducers, algebraic structures or promises. Would ES6 already be in use, all of these would have agreed on common names in the global symbol registry, instead of relying on strings like these or the then method.
Another good example would be custom hooks defined by your engine, e.g. a Symbol.inspect = Symbol.for("inspect") that you can use to define custom stringification behavior to be used by console.log. Admittedly, that symbol does not necessarily need to be made available through the global symbol registry, it could as well be put on that specific library object (e.g. console.inspect = Symbole("console.inspect")).
And how would I avoid name collisions in that global registry?
Just like you previously did with properties, or global module objects: by using very long, very descriptive names - or by good faith. Also there are some naming conventions.
I invented the most useful feature of Symbol.for() call. If there is using symbols in your code sometimes it is difficult to use conditional breakpoints while debugging. For example, you need to catch if the variable equals the value which is of symbol type and this value binded in the different module. The first difficult way is to use this value as a constant and export it from that module. In this case, the condition of the breakpoint will look:
catchedVariable === exportedSymbolConst
But the easiest way is to temporarily change the code inside the module adding .for to Symbol. Then you can write the condition:
catchedVariable === Symbol.for('string_key')
After the successful debugging you will be changing the code back just removing .for part.

Cross Browser Valid JavaScript Names

Before you quickly post with "RTFM" or with a bunch of links I have visited, I am fully aware of the documented reserved variable names not to use.
The best lists I could find are here:
http://es5.github.com/x7.html#x7.6.1.1
and
http://www.javascripter.net/faq/reserved.htm
What I am asking for are the variable names that are invalid on 1 or 2 browsers only.
For example I can define print but this will cause an error as print is already defined on the global scope window. Why isn't this documented as a reserve keyword?
Is there a big list of variable names to avoid?
What I am asking for are the variable names that are invalid on 1 or 2 browsers only.
If any such words exist, that browser would be non–compliant with ECMA-262. Only the reserved words in ECMA-262 are "invalid variable names" (provided the name is otherwise compliant with the criteria for variable names, such as allowed characters).
Why isn't [print] documented as a reserve keyword?
Reserved words can only be defined by standards that have a concept of reserved word, the only standard relevant to scripting DOMs in browsers that has that concept is ECMA-262. And it doesn't list print as a reserved word, so it isn't one.
There are various DOM standards that define host objects and their properties, the closest they might get to the concept of reserved word is that of a read–only property, or one that is not writeable. window.print is defined in HTML5, which doesn't define it as not being writable or that it should throw errors if assigned to or attempts are made to modify it. So it doesn't exhibit any behaviour approaching that of a reserved word.
Is there a big list of variable names to avoid?
No, because there aren't any. However, host objects (like window) have default properties that are writeable, you should avoid overwriting them. They should be listed in various places, like the HTML5 specification and browser vendor documentation.
e.g. the following links for the window object:
W3C HTML5 window object: http://www.w3.org/TR/html5/browsers.html#the-window-object
MDN window object: https://developer.mozilla.org/en/DOM/window
MSDN window object: http://msdn.microsoft.com/en-us/library/ms535873(v=vs.85).aspx
In addition, there is a simple for..in loop (per Berji's answer) to discover the enumerable properties at a particular time, however that may not be a comprehensive list of all possible property names and will include user defined properties along with default browser properties without distinction.
It is a better strategy to adopt a naming convention that avoids likely property names and minimise the use of global variables (i.e. user defined properties of the window object).
If you want a big list of browser-defined variables to extend the official list of reserved keywords, type the following into your console on an empty page (about:blank):
>>> Object.getOwnPropertyNames(window)
>>> Object.getOwnPropertyNames(Object.getPrototypeOf(window)) // sometimes not Object
which will yield an Array of strings you definitely should not use. It includes "print", too.
Yet it will be browser-dependent, because some do not implement all the cool HTML5-drafted stuff that uses the Window interface; e.g. you won't find "Worker" in IE9, "openDatabase" in FF and so on. Also, it might not list legacy properties like "onload", altough you will be able to to get a property descriptor for it (and "onload" in window === true).

Categories

Resources