What is the benefit of this JavaScript pattern based on an IIFE? - javascript

I master the Javascript IIFE essence, but while reading this page, I'm kinda confused of the usage.
It sounds that the following JavaScript pattern is pretty common:
(function(something) {
something.foo = 123;
})(something || something = {})
A usage example:
(function(something) {
something.foo = 123;
})(something || something = {})
console.log(something); // {foo:123}
(function(something) {
something.bar = 456;
})(something || something = {})
console.log(something); // {foo:123, bar:456}
As something is defined in the global scope, what is the benefit of this pattern in relation to the following trivial code:
var something;
something.foo = 123;
something.bar = 456;
Which use case would it make sense to use it?

You get a closure over something which ensured that even though some other code overrides it's in global scope you will still have the right reference to that something, it's better illustrated with jQuery and jQuery.noConflict();:
<script src="/path/to/jquery.js"></script>
<script>
(function($) {
// Here $ is jQuery
// Something asynchrone is happening:
setTimeout(function() {
// But $ is still jQuery
}, 1000);
})($);
</script>
<script>
// Someone calls jQuery.noConflict();
jQuery.noConflict();
// And now $ is not jQuery
</script>

Lets say you have a namespace for your application myApp. You have several scripts that add functionality because like a good developer you've broken your application up into different chunks. Also like a good web developer you're loading those scripts asynchronously, you don't know what order they are going to be added in. So you have each module conditionally create the namespace for the app if it doesn't exist (the (myApp || {}) part). You also want to hide the internal functionality of the module from stuff that doesn't need to know about it, so you pass your 'namespace' object into a function that creates a closure and attaches the module's API to the namespace object myApp.
// async loaded script for the foo 'module'
(function(myApp) {
var myPrivate = 3; // hidden in the closure
myApp.getFoo = function() { return myPrivate; };
}(myApp || {});
This pattern is not without its flaws (what if myApp.foo depends on myApp.bar?) which is why its largely been replaced by browserify/require.js/webpack/etc.

Related

Define all external JavaScript in a pre-existing namespace

I am fully aware of the dangers of eval and such, so please don't waste your time commenting on how these hacks are hacks.
Say I'm using a third-party JavaScript library, but I'd like all of it's code to be defined within a particular namespace... that I also don't control. For example:
<script src="http://example.com/library.js>
<!-- library.js contains:
var x = 0;
function foo() {}
-->
I'd like to be able to define x and foo in the context of, say, namespace Bar, instead of the global context (window).
Assuming Bar is defined, but in another external js file that I don't control, I have tried some hacks, for example:
<script>
var externalCode = $.ajax("http://example.com/library.js");
eval.call(Bar, externalCode);
// and also tried:
(function(str){ eval(str); }).call(Bar, externalCode);
</script>
But I am not able to access Bar.x nor invoke Bar.foo().
Basically, I want to achieve the results I would get if I pasted the contents of library.js inside my Bar namespace, a la:
var Bar = {
x: 0,
foo: function() {}
}
However, I am trying to do this when I also lack control over the Bar namespace. Hence I can't "copy and paste." Another related example is how we can "punch in" new methods into pre-existing class definitions in Ruby.
Lastly, my specific use case is that I'm trying to "inject" everything from p5.js into the Opal namespace.
A simple solution that works in browsers today is:
<script src="http://example.com/library.js>
<!-- library.js contains:
var x = 0;
function foo() {}
-->
<script>
$.ajax('/library.js', function(jsString) {
var wrapped = `function() {
${jsString};
Bar.x = x;
Bar.foo = foo;
}();`
eval(wrapped);
});
</script>
However, a solution that doesn't require listing modules is EcmaScript 6 modules. If you transpile it with https://babeljs.io/, it can work with today's browsers.
//------ main.js ------
import * as Bar from 'lib';
console.log(Bar.foo()); // no error
console.log(Bar.x); // 0
If you need it to work in all browsers today, and don't want to transpile your code, you'd need the first example, which could be generalized as
function importIntoNs(ns, scriptUrl, symbolNames) {
$.ajax(scriptUrl, function(jsString) {
var wrapped = `(function() {
${jsString};`;
symbolNames.forEach(symbolName => {
wrapped += 'this.' + symbolName + ' = symbolName;\n' ;
});
wrapped += '})';
eval(wrapped).apply(ns);
}
}
importIntoNs(Bar, 'http://example.com/library.js', ['x', 'foo']);
If anyone wants to downvote because of the eval, remember that the OP is already going to execute the script no matter what if they put it in a <script> tag.
Here's a working example without fetching the script.
function importScriptIntoNs(ns, jsString, symbolNames) {
var addSymbols = '';
symbolNames.forEach(symbolName => {
addSymbols += 'this.' + symbolName + ' = ' + symbolName + ';\n';
});
var wrapped = `(function() {;
${jsString}
${addSymbols}
})`;
eval(wrapped).apply(ns);
}
var Bar = {};
var jsString = `
var x = 'It works';
function foo() {alert(x)}
`;
importScriptIntoNs(Bar, jsString, ['x', 'foo']);
Bar.foo()
One way to handle libraries and other dependencies without polluting the global scope is to use some kind of Asynchronous Module Definition. A good one that I like to use and recommend is Require.js.
The whole idea behind it is that you're able to bundle your libraries and dependencies into modules and call on them when you need, without simply loading everything on the global scope.
Here is an example of how you might use it in your situation:
require(['http://example.com/library.js'], function(Bar){
// library.js is now bound within this scope under the alias Bar
});

Javascript Module pattern - how to reveal all methods?

I have module pattern done like this:
var A = (function(x) {
var methodA = function() { ... }
var methodB = function() { ... }
var methodC = function() { ... }
...
...
return {
methA: methodA,
methB: methodB
}
})(window)
This code let's me call only methA and methB() on A which is what I want and what I like. Now the problem I have - I want to unit test it with no pain ot at least with minimal efforts.
First I though I can simply return this but I was wrong. It returns window object.(can someone explain why?).
Second - I found solution somewhere online - to include this method inside my return block:
__exec: function() {
var re = /(\(\))$/,
args = [].slice.call(arguments),
name = args.shift(),
is_method = re.test(name),
name = name.replace(re, ''),
target = eval(name);
return is_method ? target.apply(this, args) : target;
}
This method let's me call the methods like this: A.__exec('methA', arguments);
It is almost what I want, but quite ugly. I would prefer A.test.methA() where test would never be used in production code - just for revealing private methods.
EDIT
I see people telling me to test the big thing instead of the small parts. Let me explain. In my opinion API should reveal only the needed methods not a bunch of internal functions. The internals because of their small size and limited functionality are much easier to test then test the whole thing and guess which part gone wrong.
While I may be wrong, I would still like to see how I could return references to all the methods from the object itself :).
Answer to your first question(you return this, but it returns window, not the object you wanted): in javascript this inside the function returns global object unless this function is a method of the object.
Consider next examples:
1) this points to the global object ():
function(){
return this;
}
2) this points to the object:
var obj = {
value: "foo",
getThisObject: function(){
return this;
}
}
Your case is example #1, because you have a function, that returns an object. This function is not a method of any object.
The best answer to your second question is to test only public methods, but if
that is so important for you, I can propose next:
create your modules dynamically on server side.
How it works:
create separate scripts for functionality you want;
create tests for these separate scripts;
create method that will combine scripts into one however you want;
to load script, reference to the combining scripts method.
Hopefully, it can solve your problem. Good luck!
Why not use namespaces to add your modules and public methods to js engine. Like this:
window['MyApp']['MODULE1'] = { "METHOD1" : {}, "METHOD2" : {}};
I write modules like this Sample module in JavaScript.
And test it like this: Simple unit testing in JavaScript
The use of eval() is generally not good idea.

Aliasing a function object in JavaScript

Disclaimer: I am using ExtJS 3, but I don't think it's very relevant to the question, outside of the common use of it's namespacing function.
I have a singleton that's declared in a really long namespace like this:
Ext.ns("REALLY.REALLY.LONG.NAMESPACE");
var Singleton = (function() {
var foo = {
bar: "baz"
};
var privateFunction = function(param){
// ...
return foo;
};
var single = Ext.extend(Object, {
constructor: function(config) {
Ext.apply(this, config);
},
otherFunction: privateFunction,
publicFunction: function (someObject){
// do stuff with someObject
}
});
return single;
})();
// Make it a singleton
REALLY.REALLY.LONG.NAMESPACE.Singleton = new Singleton();
I use it in other modules via calls like REALLY.REALLY.LONG.NAMESPACE.Singleton.otherFunction(); and REALLY.REALLY.LONG.NAMESPACE.Singleton.publicFunction(myObject); . I'm wondering if I can swap out those calls by setting up the client module with an alias to the singleton, i.e. var singleton = REALLY.REALLY.LONG.NAMESPACE.Singleton; , so that I can call singleton.otherFunction();. I'm wondering if this is an anti-pattern , or if there are any pitfalls (memory?) I might run into through this usage.
Thanks StackOverflow!
I'm wondering if I can swap out those calls by setting up the client module with an alias to the singleton
Yes, you can.
I'm wondering if this is an anti-pattern , or if there are any pitfalls (memory?) I might run into through this usage.
No, there aren't any that I can think of and it is faster than calling the fully-qualified version.
Local Alias Pattern
Example:
function somefunc(){
var singleton = REALLY.REALLY.LONG.NAMESPACE.Singleton;
singleton.publicFunction();
};
Or:
(function somfunc(singleton){
}(REALLY.REALLY.LONG.NAMESPACE.Singleton));
Test Results:
http://jsfiddle.net/jMg9A/
There is no issue with creating a reference to the original "object". In many cases we create a namespace to organize our code, but of course, this can lead to really long namespaces that we really don't wish to reference later, thus creating a local reference to that namespace is an excellent idea so that you can change it in one place instead of various places.
I don't really see an ant-pattern here, instead I see an opportunity to make it simpler for yourself and probably a little more manageable from a developer standpoint.

Javascript Module Pattern Help

The problem I have is that there are a set of variable values / properties in one file and a library in another file. I have started refactoring the code but still need to keep variable values(dynamic) and library(static) differently.
I am using namespacing and overall want only one global namespace.
The problems I have at the moment:
1. How can I still keep one global namespace
2. What is the best way to read the values from one file and use it in the library present in another file.
e.g I came up with something like
//File ONE with values
var main.dynamicvalues = (function(){
var a = 10,
b = 20,
c = 30;
return {
a:a,
b:b,
c:c
}
}());
//File TWO with core Library
var main.library = (function(){
//Various Private functions that need to use a,b,c variables from above main.dynamicvalues namespace
return {
//Public functions again need to use a,b,c from above namespace.
}
}());
Is there a way I can have a pattern so that I keep only one global namespace and can refer to variables directly without having to use maincode.values.a, maincode.values.b, maincode.values.c or something like this in maincode.library.functions
Thanks
Sparsh Gupta
This approach is a little better, but it's not exactly what you're looking for.
var main = {};
main.dynamicvalues = (function() {
// same as before
})();
main.library = (function(dyn){
// use dyn.a, dyn.b etc
return {
// same in here
}
}(main.dynamicvalues));
Create a new file (maybe name it something like "common.js") and put the values there.
You can try RequireJS. This will let you do what you want with no global namespace at all (if you'd like to). In addition it will give you non-blocking script loading, easy way to handle dependencies and a build tool.
On the other hand, it can deprive you of the joy of investigating things for your own and better understanding of js architectural patterns.
Your code with RequireJs could have looked like this:
// File one with values, let's name it values.js
define([], function() {
var a = 10,
b = 20,
c = 30;
return {
a: a,
b: b,
c: c
}
})
// File two with library
define([
// load values.js as a dependency
'values'
// what is returned in values.js can be passed as an argument to the callback
], function( values ) {
values.a === 10 // true
})

What is meant by “leaking” into global scope?

A while ago, I offered-up a JavaScript design pattern (the Module Pattern - see below) that I got from a John Resig example as part of a solution to someone’s question and I received the following comment:
“…that pattern is a bit over
engineered and not that good. Still
leaking into global-scope. and your
not opening yourself to async loaders.
But it is better then just ad-hoc
coding !”
So…
If “leaking” into global scope means “your object gets appended to the browsers window (object)”…then everything already gets appended (globally):
This “leaks” into global scope:
window.jQuery
…just call: window.jQuery and it resolves as a function();
This “leaks” into global scope:
function HelloWorld() { alert(‘Howdy’); }
…just call: window.HelloWorld() and you will get ‘Howdy’.
This “leaks” into global scope:
var myVariable = 10;
…just call: window.myVariable and you will get 10
If the commenter is correct, then all the above “leak” into global-scope. So, personally, I don’t see a way NOT to “leak” into global-scope as even your form controls exists there (as well).
As such, here are my questions…
What is meant by “leaking” into
global-scope?
Why is that bad?
How do you avoid it?
When wanting to create persistent
custom-objects, why is the Module
Pattern (below) bad?
Design patterns let you encapsulate
complex logic, is encapsulation
suddenly bad simply because we’re
writing in JavaScript?
Or...is this commenter simply wrong?
Here is the Module Pattern I Mentioned Above:
<script type="text/javascript">
var myNamespace = (function($) {
var publicInstances = {};
// ***********************
// myObject
publicInstances.myObject = myObject;
function myObject() {
/// <summary>A pointer to this</summary>
var self = this;
this.someProperty = new String();
this.initialize = function() {
/// your code here
}
this.someMethod = function() {
/// your code here
}
self.initialize();
}
return publicInstances;
})(jQuery);
jQuery(document).ready(function() {
// Use would look like
var myInstance = new myNamespace.myObject();
});
</script>
UPDATED:
I’m satisfied with the answers below and want to thank everyone for taking the time to comment.
TO RECAP THE ANSWERS BELOW:
"Leaking" into global-scope occurs when something used in local-scope is unintentionally made available to the global-scope (e.g. the window object). This is bad because it opens the page to potential naming collisions which could result in variables resolving to unexpected values or types.
Intentionally making a variable global is not considered a "leak". However, properly namespacing the object is required to reduce potential for said naming collisions.
You cannot avoid globally-scoped variables, but you can reduce the above risks by using asynchronous-loaders and defining-modules made available in plug-ins like RequireJS or Curl.
"Leaking" into global scope is when something used in a local scope is unintentionally made available to the global scope. That means assigning to a variable not already defined in the current scope:
function myFunction() {
a=1;
}
myFunction();
alert(a);
//-> 1
It's bad because there could be naming collisions resulting in variables with different values/types than expected. It can also lead to a bug in older Internet Explorers when you forget to use the var keyword for a variable used in a for statement.
I wouldn't class intentionally making a variable global as "leaking", because it's more like you're "pouring" it into the global scope. However, this is still often considered bad practice by some (although I think that's a little melodramatic) because there are still potential naming collisions with current properties of the window object, or variables set by other scripts and libraries.
[[Short story]]
Don't make global variables ever and use an async module loader like requirejs or curl
[[Long story]]
That comment was poorly structured.
There is nothing wrong with the module system. I was complaining about using global variables at all. (I still think the full generic module pattern is bloated).
Whether you should avoid all global variables is a different question and I think a matter of style. You can either use an async loader to pass modules around or using window to pass modules around.
What is meant by “leaking” into global-scope?
What I meant was your creating global variables. Minimising the use of global variables is a pattern. In functional style programming it's possible to have zero global variables but this is a different pattern from using global modules.
Why is that bad?
Having any state globally can cause that state to be corrupted.
How do you avoid it?
You can't. You can minimize the amount of global variables though. To avoid having global state completely you can use asynchronous loaders. These define a few global variables for you that you can then use.
When wanting to create persistent custom-objects, why is the Module Pattern (below) bad?
There is nothing wrong with the module pattern. The problem is storing your module globally. The issue is having global namespaces.
Design patterns let you encapsulate complex logic, is encapsulation suddenly bad simply because we’re writing in JavaScript?
Now that I've cleared up the intent of the comment this question isn't really relevant
Or...is this commenter simply wrong?
The comment was poorly phrased at best. I objected to global namespaces rather than modules, but did not state this properly.
The alternative is using asynchronous loaders and defining modules. These can be narrowed down to two global variables. define and require.
require = function(moduleName, callback)
This will get a module and then return it to you.
define = function(obj)
this defines a module.
The concept here is that you multi file code as follows:
// main.js
require([
"foo.js",
"bar.js",
...,
], function(foo, bar, ...) {
// do stuff
});
//foo.js
(function() {
var namespace = modulePatternCode;
...
define(namespace):
})();
//bar.js
(function() {
var namespace = modulePatternCode;
...
define(namespace):
})();
Your module only "leaks" it's namespace holder so it's pretty acceptable.
Loader example using RequireJS:
Define a utilities module in utils.js:
define(function () {
return {
each: function (iterable, callback) {
// ...
},
map: function (iterable, mapper) {
// ...
}
};
});
Use the above module in another module, say math.js:
define([ "utils" ], function (utils) {
return {
sum: function (numbers) {
var sum = 0;
utils.each(numbers, function (n) {
sum += n;
});
return sum;
},
average: function (numbers) {
return this.sum(numbers) / numbers.length;
}
};
});
And you can use math.js in another file, say main.js:
console.log("About to add 1-3");
require([ "math" ], function (math) {
console.log(math.sum([ 1, 2, 3 ]));
});
You can still have namespaces, and still keep them warm and cozy inside modules:
namespace.js:
define([ "foo", "bar", "moo" ] function (foo, bar, moo) {
return {
foo: foo,
bar: bar,
moo: moo
};
});
Then the rest of the modules can use this namespace during definition:
define([ "namespace" ], function (namespace) {
namespace.foo(42);
});
Or at runtime, in some other module:
define(function () {
return {
initialize: function () {
require([ "namespace" ], function (namespace) {
namespace.foo(42);
});
}
};
});
In the usages above, nothing but define and require are global. Of course, these are just illustrative examples, as there are many different flavors of defining/using modules in RequireJS.

Categories

Resources