Break the encapsulation of immediately executed anonymous functions? - javascript

A common Javascript pattern is:
(function() {
var localScopedValue = "foobar";
// code... functions...
}());
The self-executing or immediately executed anonymous function creates a scope for everything inside it to prevent pollution of the global scope, and it also theoretically prevents anyone from getting references to either the function object or anything defined inside it from an outside script, browser console, etc. That's the idea, anyway.
However, Javascript being a dynamic language with reflection, etc., I am wondering if there is any way -- no matter how hackish (but not editing any existing code) -- of getting references to locals that are not deliberately exposed from Javascript code.
Reason: pure curiosity / breaking things.
Adding: Things I'm looking at include Function.caller and event listeners, basically anything where items inside the IIFE are known to call/hook out, but I can't put together the complete package.

JS doesn't have "real" reflection - all it has is the ability to access the properties of an object using a variable as a key with myObject[myVar] syntax instead of myObject.myProperty.
This therefore provides no access to lexically scoped private variables.

Related

Why does Google Closure Compiler adds variable to the global namespace when the original namespace was empty?

I have a long script nicely wrapped into a (function() {/.../})() to avoid all kind of name pollution. It is 100% typed with zero warning.
I found out that Google Closure compiler starts by redefining i and j in the global namespace which feels both unnecessary and dangerous, especially since I am compiling a script that has zero interference with the namespace. (the compiled script starts with var i=null,j=!1;, for compactness reasons I believe).
I can think of a work around which is to wrap it using the --output_wrapper but I can't think of a reason why Google would pollute the namespace like this.
Is there any?
The compiler expects that it's given all relevant JavaScript so that it doesn't need to worry about clashes with other scripts. Therefore it assumes that it can unwrap the "unnecessary" anonymous function.
From the FAQ:
When using Advanced Optimizations, Closure Compiler adds new variables to the global scope. How do I make sure my variables don't collide with other scripts on the page?
Closure Compiler's advanced optimizations mode assumes that it's ok to add new variables to the global scope.
In JavaScript, it's often standard practice to wrap your code in an anonymous function, so that variables don't pollute the global scope. Closure Compiler has an --output_wrapper flag for exactly this purpose. Invoking it as --output_wrapper "(function() {%output%})();" will wrap your code in an anonymous function at compile-time.
Closure Compiler users often find it easier and simpler to do this wrapping at compile-time, rather than writing the anonymous function wrapper in the original source code.

Why do you need to pass in arguments to a self executing function in javascript if the variable is global?

I was looking at the code for the underscore.js library (jQuery does the same thing) and just wanted some clarification on why the window object is getting passed into the self executing function.
For example:
(function() { //Line 6
var root = this; //Line 12
//Bunch of code
}).call(this); //Very Bottom
Since this is global, why is it being passed into the function? Wouldn't the following work as well? What issues would arrise doing it this way?
(function() {
var root = this;
//Bunch of code
}).call();
I suspect the reason is ECMAScript 5 strict mode.
In non-strict mode, this IIFE
(function() {
console.log(this); // window or global
})();
logs the window object (or the global object, if you're on a node.js server), because the global object is supplied as this to functions that don't run as a method of an object.
Compare that result to
"use strict";
(function() {
console.log(this); // undefined
})();
In strict mode, the this of a bare-invoked function is undefined. Therefore, the Underscore authors use call to supply an explicit this to the anonymous function so that it is standardized across strict and non-strict mode. Simply invoking the function (as I did in my examples) or using .call() leads to an inconsistency that can be solved with .call(this).
jQuery does the same thing, and you can find several answers to your question on SO by searching along those lines.
There are two reasons to have an always-available global variable like window in local scope, both of which are for the sake of fairly minor optimizations:
Loading time. Looking up a local variable takes a tiny bit less time than looking up a global variable, because the interpreter doesn't have to look as far up the context tree. Over the length of a function the size of Underscore or jQuery, that can theoretically add up to a less-trivial amount of time on slower machines.
Filesize. Javascript minification relies on the fact that variables can be named anything as long as they're consistent. myLongVariableName becomes a in the minified version. The catch, of course, is that this can only apply to variables defined inside the script; anything it's pulling from outside has to keep the same name to work, because if you shrink window down to pr the interpreter won't know what the hell you're talking about. By shadowing it with a reference to itself, Minify can do things like:
(function(A){ B(A, {...}); A.doStuff(); //etc });})(window)
and every time you would otherwise have put window (6 characters) you now have A (1 character). Again, not major, but in a large file that needs to explicitly call window on a regular basis for scope management it can be important, and you've already got an advantage by a few characters if you use it twice. And in large, popular libraries that get served by limited servers and to people who might have lousy Internet plans, every byte counts.
Edit after reading comments on question:
If you look at what function.call() actually does, your second snippet wouldn't actually work - the this being passed in isn't an argument, it's an explicit calling context for the function, and you have to provide it to .call(). The line at the beginning of the file serves the two purposes above. The reason for setting the context explicitly with call is futureproofing - right now, anonymous functions get the global context, but theoretically that could change, be discouraged in a future ECMA specification, or behave oddly on a niche browser. For something that half the Internet uses, it's best to be more explicit and avoid the issue entirely. The this/window choice at the top level I think must have something to do with worrying about non-PC devices (i.e. mobile) potentially using a different name for their top-level object.

Why wrap every prototype "class" object with an anonymous function in JS?

Looking at this JS code by David Fowler he wraps every "class" with an anonymous self executing method where he sends in jQuery and window. I get that this is a way for ensuring that $ and window are actually the global jQuery and winndow variables you'd expect them to be.
But isn't this a bit over-protective? Should you protect yourself from someone else changing the $ and window variable - is there actually code that does that, and if so why? Also, are there other advantages to wrapping everything like this?
If I remember correctly there are some other libraries than jQuery using the $.
The concept of using function context to create local / function scopes is all about to protect your own code. This especially makes sense if you expect your Javascript code to run in an environment where multiple other (maybe even unknown) scripts may get loaded.
So, if some other Javascript code which got load before your own, assigns window.$ with some other value (it might load the prototype framework for instance), then your code is already screwed if you try to access jQuery specific things.
Another point there is the "a--hole"-effect. Someone creates a line like
window.undefined = true;
...
Now, all your checks against undefined will pretty much fail. But by explicitly creating those variables/parameters and filling them with the values you expect, you can avoid all those problems.
(function(win, doc, $, undef) {
}(window, window.document, jQuery));
Generally most top-level JavaScript code should be wrapped in an IIFE, whether they pass in particular variables or not. This prevents variables created with var from polluting the global scope.
Another small benefit is minification: if you minify your code, making window into a "local variable" by passing it in as a parameter allows the minifier to rename it. This benefit goes away if you gzip, however, so it's not a real win.
Mostly people just pick a pattern for their IIFEs and stick with it, so in his case he's decided this is they way he writes his .js files and he does so uniformly. Having a uniform standard is valuable in and of itself.
To clarify, the code can be written in slightly longer form with
(function () {
var $ = jQuery;
var window = window;
// ...
}());
The code inside the anonymous function is the the function scope, so it prevent confliction with the global variables.
Imaging that if every jQuery plugin is not wrapped in a anonymous function, then there will be a global variables hell.
It's just to preserver integrity.
$ can be Prototype, so sending jQuery as argument will save your code if someone else add a library/variable which overwrite $.
About the second argument "window", I see it as a module you want to write on.

Will this javascript cause memory leak?

function outer(){
var a, b, c;
function inner1(){
...
}
function inner2(){
...
}
inner1();
inner2();
...
}
I want to keep the global namespace clean so I wrote above code. Inner functions are only used by code inside Outer. But after that I begin to thought if this will cause any memory problem. I'm not sure whether the inner functions are created beforehand or created each time the outer() is called? And will them cause memory leak?
Could someone help explain what will happen when outer() is called and when it returns? And please refer me if there are any good books or articles about javascript memory management. I always get confused by such problems. Thanks.
Not sure about first part but there is a similar question about the second part:
Do you know what may cause memory leaks in JavaScript?
How do I track and debug JavaScript memory leaks in Firefox?
The main problem that causes memory leaks in browsers with JavaScript is the fact, that the DOM and JS have two independet garbage collectors. If you begin to have references to DOM elements in your closure function and then again backreference to something inside the function you will face problems. Your structure is not leaking, but you want to do some more stuff and that maybe leaking.
In answer to your question about the creation of the inner functions: I believe your inner functions are created/defined every time you run outer(), and most JS interpreters should garbage-collect them after outer() runs, along with all the other variables in the function scope - unless outer() "exports" these inner functions outside of its own scope, e.g. assigning them as event handlers or including them in a return statement for later use.
Unless you put some other code inside - you should not worry about leaks in such simple closures. Modern javascript engines handle those very well.

Pass data to encapsulated javascript code

in my webapp I have a variable like this
var data = {
getItem: function(key){
...
}
}
In all of my scripts I can use
data.getItem("Test");
But how can I use it in jquery plugins? Plugins often have following structure
(function($, window, document) {
//....plugin-code
});
How do I call this kind of structure? Is it possible to use my global data variable in such plugins?
If your data variable is global, then yes you can use it anywhere, including inside jQuery plugins.
You'll need to make sure that data is defined before any self-executing functions that are going to use it.
Actually they tend to have structure
(function($) {
// plugin-code
})(jQuery);
the points being that
they can assume that $ in this scope will always be jQuery, regardless of anything else loaded that defines $ e.g. prototype
everything is defined inside this closure and so only what you choose to expose (by $.fn or $.extend) is leaked out to the outside world
Obviously if it's just your plugin in your environment where you can assume you're always running $ = jQuery then you don't need these. (Yours also has document and window: I've never seen these overridden and I'm not sure what you'd pass in as arguments here other than document and window themselves?)
Were you asking about defining data inside the plugin or pulling it in from outside the plugin scope? There's no restrictions of what you can write inside, so if you define and use it inside then your code will work exactly as befoer. If you need to access data defined inside from the outside then you'll need to leak it out somehow, e.g. adding an accessor method to one of $, document or window.
If you're pulling in data from outside the plugin scope then you can still access global variables from inside your closure, or you could pass it in as an extra argument - I don't think it'd make any difference.

Categories

Resources