Having the follwoing 2 patterns to generate a reliable local variable with the name undefined that should contains undefined is any of the 2 patterns safer (less error-prone / breakable) than the other?
pattern1
function(arg1,arg2,....,undefined)
{
}
pattern2
function(arg1,arg2,....)
{
var undefined;
}
Maybe I am just to worried, but the pattern1 type seems breakable by simply passing a variable to the function which then is assigned to the local variable undefined.
PS:
Also it seems newer browsers (i.e. FF 33 / Chromium 37) do not allow this pitfall anymore
window.undefined = "omg";
"omg" == undefined; //true
indeed they produce this
window.undefined = "omg";
console.log(window.undefined); // logs undefined and NOT "omg" in FF33/Chromium 37
hence making the safety patterns superflous anyway.
To me it seems agreeable that window.undefined may never be reset (readonly and being undefined) and in effect I wonder why there has anyway been a browser implementation which allowed for this being-a-bug-only-feature (at least I cannot see a use-case)?
Maybe I am just to worried, but the pattern1 type seems breakable by simply passing a variable to the function
Yes, and that is why this pattern is only used in IEFEs where you yourself are the only caller of that function:
(function(arg1, arg2, …, undefined) {
// …
}(val1, val2, …));
Also it seems newer browsers do not allow this pitfall anymore
Yes, all engines that implement ECMAScript 5 don't allow this - the global undefined variable is non-writable just as you described.
hence making the safety patterns superflous anyway
Indeed, using it feels a lot like cargo-cult programming. Everyone expects ES5 today anyway.
I wonder why there has anyway been a browser implementation which allowed for this being-a-bug-only-feature (at least I cannot see a use-case)?
It was simply a lack in the ES 3 spec. This never has been a "feature", it simply had been forgotten to be specified.
Both pattern will essentially produce the same effect and its third party library/framework which adopted this approach to minimize the accidental redifinition of undefined.
undefined is a property of the global object, i.e. it is a variable in global scope. The initial value of undefined is the primitive value undefined.
Prior to ECMAScript 5/modern browsers anyone could configure/rewrite this variable to any value. This posed a problem with third part libraries/frameworks where
undefined = 5;//now undefined is of type number
//code inside library
(function (arg1){
if(somevar === undefined){//unintentionally it will compare somevar to 5
}
})(arg1);
Thus to minimize the effect from global variables they adopted below approach
(function (arg1, undefined){//since only one param is passed the second param undefined would indeed will be of type undefined
if(somevar === undefined){//it will compare somevar to undefined
}
})(arg1);
The first pattern you provided is incomplete. It's proper use is when creating inline closure, so that you ensure the correct value of undefined by not passing any value for the last argument to the closure function.
(function (undefined) {
// ... your safe code here
})();
Then it is equal in consequences to the second pattern. However, the first pattern is usually the one that is used, because enclosing all your code in a closure is a good idea under any circumstances (to avoid leaking variables into global scope).
Related
Pretty straightforward question. For example, are these equivalent?
window.open('http://someurl.com')
window.open('http://someurl.com', undefined)
Part of me suspects that it might depend on the function itself, but I'm not sure.
In short: In the vast majority of cases, passing undefined is equivalent to leaving the argument out.
However, within a function, you can differentiate between an omitted argument and one that was passed as undefined. While I would never recommend using that distinction to change behavior, you can see the difference between the two if you access the special arguments variable within your function:
function logNumArgs() {
console.log(arguments.length)
}
logNumArgs() // 0
logNumArgs(undefined, undefined) // 2
Note: the arguments variable is only accessible on non-arrow functions!
MDN - Arguments Object
I'm writing a library that exposes the following function
function call(instance, func, arguments) {
return {
call: {
instance: instance,
func: func,
arguments: arguments
}
}
}
Is the name arguments ok to use? It's really the best name for it, but I don't want to clash with the builtin variable. It works in Node. Will this work in all browsers and JavaScript environments?
Edit:
Note that the above function does work as expected in Node. What I'm wondering is whether this will work everywhere.
I'd rather not rename it unless there's a technical reason to. I'd really like this external-facing function and the docs to reflect this parameter name, because the returned object is going to be serialized as JSON and used across languages.
It is okay to use the name arguments in "sloppy mode", but not recommended.
It is forbidden in strict mode, which all new code should use if the author cares about code quality.
function a(arguments) {
console.log(arguments);
}
a(1);
// Prints "1"
(function () {
'use strict';
function a(arguments) {
console.log(arguments);
}
a(1);
}());
// Uncaught SyntaxError: Unexpected eval or arguments in strict mode
This is akin to naming a variable "Object". Maybe in some obscure context it makes sense to use that name, but by doing so you lose access to the global Object object and useful methods on it like Object.keys. Similarly, by making this poor naming decision, you can no longer manipulate the arguments object, which is varargs in JS.
In the interest of improving the maintainability of your code, it is best to avoid creating ticking time bombs like this one. There is a good reason why it is not allowed in strict mode: It is likely to cause misery for anyone who wants to use arguments as it is typically used.
It looks like that is taken. arguments is a quick, array-like way to get all the arguments of a function. See this explaining it.
Maybe you could use parameters instead?
EDIT: To see how this variable works, I wrote this:
function sayHelloTo(objectToSayHiTo){
alert("Hello "+arguments[0]+"!");
}
sayHelloTo("world");
EDIT #2:
Apparently, it will not be affected:
function sendGreetings(name, arguments){
alert("I'm "+name+"!");
for(var count=0;count<arguments.length;count++){
alert("Hello "+arguments[count]+"!");
}
}
sendGreetings("kittycat3141", ["world", "StackExchange", "Joe"]);
However, I haven't tried all browsers yet.
EDIT #3
I have tried 5 major browsers (IE, Chrome, Safari, Firefox, and Opera) and the code above works properly. However, as iCobot said in the comments, it is best not to use builtin names because it can save you confusion and frustration later, for you and anyone reading the code.
I've seen this syntax for creating an anonymous constructor function in JavaScript:
var Application = Application || {};
!function(window, Application) {
Application.property = {/*...*/}
Application.method = function(){/*...*/}
}(window, Application);
I want to understand what the following parts here:
What is the advantage of using first line (i.e. var o = o || {};) vs just stating var o = (function(){})();?
Why ! is used in front of function?
Why would I pass window or Application as parameters when they are global object?
Is this the most convenient way for anonymous constructor function and how is this better than:
4a)
var Application = {
property: {},
method: function(){}
}
or 4b)
var Application = (function() {
var method = function(){/*...*/}
return {method:method};
}());
The first line is to ensure that Application always exists, and is generally used in cases where it's expected that Application already should exist, and the function just augments the existing object. If it doesn't exist, this makes sure that we don't get an error for accessing properties of undefined. Your examples are only equivalent in the case where Application does not yet exist. In all other cases, your code will obliterate the existing Application, which is almost certainly not the intent.
The comment from Vatev explains what the ! does. It's another syntax for making the function in question become a self executing anonymous function. (Incidentally, it also takes the return value of the function - which is currently undefined, and flips its truthyness, so it evaluates as true. Since the result isn't stored in any variable, though, that's clearly not the purpose.)
Finally, why pass window and Application into the function and use it there? This is a safety feature, in case other code changes window or Application later on. It guarantees that within the anonymous function, window and Application are exactly what you expect it to be. In the shorthand example you gave, this may appear to not matter - after all, why protect these variables if you're using them immediately and not storing them? In many cases, you return something from this function, and then window and Application would be stored in the closure, so you'd retain the variables. It makes it safe from people who later on decide to say Application = {...}.
I don't know all of the answers but I'll try to answer what I can.
Using var Application = Application || {}; simply means that you are dealing with scope. If the "Application" variable has already be defined, it will just mean that it inherits and is now available in the current scope. If not, the "||" part (means OR) means that it will be created as an empty object. You are dealing with creating an object and then acting on it, not just having the result given back raw. That's why you shouldn't use "o = (function() {...});". "o" would then be the result of the function and not the object.
The use of "!function" causes it to be treated as an expression, but this can be tricky because you may have to think in opposites. E.g. !null means you are checking that it isn't null, not that you are checking for it to be null.
Passing in the window and Application objects deal with scoping, again. It is explicitly passing them into the function, then returning them at the end. Think of this as putting clothes in the washing machine. You put them in, stuff can happen, then you get them back out. It's a really crude idea and isn't the best example, but it's how I thought of it a while back. You put clothes in, call then rinse function, then soap function, then rinse again, then spin to drain water.
Hopefully someone else can answer that, I'm not sure what the differences are.
Since two answers so far neglected these two details: A pattern used by libraries like jQuery is using the following two parameters:
(function (window, undefined) {
window.myPlugin = ...;
})(window);
There are two things going on here:
undefined is specified as a parameter, but not passed in. This way, undefined is guaranteed to have th expected value within the inner scope. This is only necessary for older browsers which allowed overwriting undefined (though it has always been considered bad practice to do so – it's just what libraries like jQuery do to avoid other code interfering with their code).
Aliasing a global object like window within the scope allows the code to be minified more (also works for undefined). Obviously, the more references you have to the aliased object(s), the more you will save:
.
(function(w,u){w.myPlugin=...;w.somethingElse=...;if(whatever===u){return;}})(window);
compared to
(function(){window.myPlugin=...;window.somethingElse=...;if(whatever===undefined){return;}})();
You won't save much with window since typically you don't wanna clutter the global object up anyway. But aliasing undefined can save you quite some space.
It's been a while since ECMAScript 5 came out and is being supported quite well in most modern browsers (IE9, CH 19+, FF 4+) and with it so is the "Immutable undefined". Though I keep seeing "undefined" being passed like so:
(function ( ..., undefined ) {
})(...);
From what I can tell Crockford's JSLint tool doesn't really like it:
Expected an identifier and instead saw 'undefined' (a reserved word).
Even though it's not being passed (there's no argument on the function call) and it's really an identifier. I understand that his tool isn't a bible we should follow to the death and on the other hand JSHint doesn't seem to care about it.
Is this still considered a best practice today and how does it affect code performance/security? Considering browser support >= IE9.
Is this still considered a best practice today and how does it affect code performance/security? Considering browser support >= IE9.
Much like undefined, Infinity is a non-writable property of the global object rather than a literal like null, so it can be used as a parameter name without raising an error. Lets consider a function like this
function example(Infinity) {
return Infinity;
}
In example, Infinity is no longer a non-writable property and instead acts like any other parameter to a function, initialised as undefined if nothing is passed or otherwise taking the value of the argument. This means in this function you can't just assume Infinity will mean Infinity, because it doesn't, but you could assume it will mean undefined.
So let's go back to the question of undefined. It will be initialised as undefined so the meaning will stay the same, however, it has now lost it's immutability within the function and therefore any typos assinging a values to undefined will have this error carried forward. Additionally, if a parameter is passed to the function the value will be different from the start.
Therefore to conclude, it does have an effect on security, as an undefined like this is no longer as "safe" because it has lost it's immutable status and can be changed.
It may be interesting to note that undefined is not actually a reserved word. If you require an undefined for compatibility, rather than adding it as a parameter name, I would suggest using a simple var undefined; at the top of the function or in the global namespace where you will find var undefined; undefined = 1; undefined; // undefined where it is immutable.
If you wanted to comply with jsLint, you could use another variable that is not a reserved word instead of undefined. The following complies with jsLint:
(function (window, document, undef) {
'use strict';
}(window, document));
You would, however, need to remember to use your newly defined variable (in this case undef instead of undefined). The strict mode above was added to comply with jsLint. This is mostly used so that you know for certain that the variable you are testing to be undefined is actually undefined.
Note, that if you're running this example in the text area provided on the jsLint website, you may need to define window and document. I was receiving two errors until I did so.
var window = window; //global window object
var document = document; //global window object
However, I'm of the opinion that:
(function (..., undefined) {
'use strict';
}(...));
is perfectly fine and more importantly, highly recommended.
There are cases where reserved words can be changed from their normal states. Such as setting undefined to true. Paul Irish discusses this briefly in his video: http://paulirish.com/2010/10-things-i-learned-from-the-jquery-source/
I have noticed jQuery and related keynote plugins like jQuery.UI pass undefined as a parameter into anonymous functions used in their module definitions, like so:
(function($, undefined) { ... })(jQuery);
Alternatively, I have noticed other plugins recommended by jQuery and/or others do NOT pass undefined in as a parameter.
This is probably a silly question, but...
Shouldn't it always be available anyway? Why pass it in? Is there some sort of other purpose or trick going on here?
There are two reasons for that:
1) If undefined is a variable in the function scope rather than a global object property, minifiers can reduce it to a single letter thus achieving a better compression rate.
2) Before ES5*, undefined was a property of the global object without write-protection. So it could be overwritten, resulting in strange and unexpected behavior. You could do something like this:
var test = 123;
undefined = 123;
if (test === undefined){
// this will actually be true, since undefined now equals 123
}
By having an function argument undefined (the name actually does not matter) which you don't pass a parameter to, you could make sure you have a variable which really is undefined so you can test "undefinedness" against this variable.
Btw. the safest method to test for undefined is: typeof ( var ) === 'undefined'
(*) With EcmaScript 5, the global properties undefined, NaN and Infinity became readonly. So with its general adoption in all modern browsers - of course with the exception of IE 9 - overwriting those values was not possible anymore.
That is done to make sure that undefined always is undefined. In older versions of the ECMAScript spec (prior to ECMAScript 5), undefined wasn't a reserved word but a regular variable. In older browsers this would be allowed for instance:
undefined = 2; // Assign a different value to undefined
// Now this statement would be true
if (undefined == 2)
So to make sure that undefined is in fact undefined, even if some other "evil" script would have reassigned undefined with another value, you create a parameter that you call undefined, and then when you call the function, you make sure to not pass a value to that parameter - thus you can be sure that the variable undefined will always be undefined within your function.
So in the case of jQuery:
(function($, undefined) { ... })(jQuery);
They pass in jQuery and assign it to the $ variable for convenience, but then they don't pass a second value to the undefined parameter, thus undefined will be undefined.
Modern browsers
In modern browsers, undefined is a non-configurable, non-writable property per the ECMAScript 5 specification.
undefined is not a reserved word in javascript, it is simply a variable. jQuery is ensuring that if some bad developer overwrites the value of undefined in their javascript, then jQuery will ignore it and establish it's own variable, undefined, which is never passed a value (see the self-executing (jQuery) at the end) and is therefore actually undefined.