I've been using a pattern in my node.js modules that seems so obvious to me that I assume there must be something wrong with it or I would see more people doing it. To keep private variables that are global to the module, I simply attach them as properties on the module object. Like so:
module.exports = {
init: function() {
module.someClient = initializeSomethingHere()
},
someMethod: function(done) {
module.someClient.doSomething(done)
}
}
This seems preferable to me than something like this...
var someClient;
module.exports = {
init: function() {
someClient = initializeSomethingHere()
},
someMethod: function(done) {
someClient.doSomething(done)
}
}
...because in the second example you need to go searching for var someClient at the top of the file to make sure that the omission of the var keyword is intentional within the init method. I've never seen this pattern used elsewhere though, so I wonder if I'm missing something that makes it less than ideal.
Thoughts?
There are a couple of possible downsides that come to mind.
1) It's technically possible for those properties to be accessed and modified outside the module, but only if a reference to the module itself is available outside it. Something that makes the module available through its own exports (module.exports = module; being the simplest example) would expose them.
2) You could have a naming conflict with a builtin property or a future builtin property that doesn't exist yet (which would cause your code to break in future versions of node.js). This could be very problematic and very hard to debug. Currently the built-in properties on a module object are: children, exports, filename, id, loaded, paths, and parent.
because in the second example you need to go searching for var someClient at the top of the file to make sure that the omission of the var keyword is intentional within the init method.
If that is the reason, you could just use a namespace that isn't module. For instance by adding var private = {}; to the top of each file and then using private.someClient instead of module.someClient.
Also 'use strict'; so that the accidental omission of var is an error and not an accidental global.
Drawbacks
Option 1: This practice is prone to naming conflict with a builtin property or a future builtin property that doesn't exist yet, as #paulpro stated in his answer.
Option 2: If you miss var keyword and expose the someClient globally. Besides you need to go searching for var someClient at the top of the file all the time.
Alternative
As JavaScript has function scope it's better to define everything within a function. Creating private and public members within a function. Below is a design pattern which one can follow:
'use strict';
module.exports = (function(){
//private
var someClient;
//public properties
var that={};
that.init = function() {
someClient = initializeSomethingHere()
},
that.someMethod: function(done) {
someClient.doSomething(done)
}
//expose only the required methods
return that;
})();
Here only exposed methods are those which are attached to that object. And all rest are private to the function scope. Even if you miss the var keyword in someClient it won't be accessible out side of the function, which won't ever happen if you use 'use strict' at the top.
Logic is first time when you require the xyz.js file it will return the that object rather than the function.
Related
I've been seeing a number of people wrapping their controllers with:
function(){
//CODE
}();
What's the benefit / goal there?
That isn't really anything related directly to Angular, it is a JS pattern know as an Immediately Invoked Function Expression.
It is one of the most useful patterns in JavaScript, primarily because of:
Code Encapsulation
Since functions have closures in JS, we can use this pattern to create private data very easily:
var index = (function iife() {
var counter = 0; // <-- this is private, only available inside the closure of inner()
return function inner() {
return counter++;
};
})();
console.log(index()); // 0
console.log(index()); // 1
console.log(index()); // 2
console.log(index.counter) // undefined
We can also pass arguments into an IIFE, which allows us to control how we access the outside context of our IIFE. For example, to make sure $ is actually the jQuery object within your code:
(function ($) {
// here have access to the global jQuery as $ regardless of what window.$ is and
// how many libraries are trying to use $
})(jQuery);
By combining the two ideas above, IIFEs can also be used to implement the module pattern, which is the basis for how RequireJS and NodeJS separate code:
var myModule = (function iife(initData) {
// we can use initData here to initialize our module if necessary
var module = {};
// private vars ...
var privateVar1, privateVar2;
// private methods ...
function privateMethod() {
console.log('yeeey');
}
module.somePublicProperty = 1;
module.somePublicMethod = function() {
privateMethod();
};
return module;
})(/* pass initialization data */);
myModule.somePublicMethod(); // 'yeeey'
The reason you'll find a lot of JavaScript code wrapped in an anonymous function is to isolate it from other code on the page.
The following code will declare a variable called name on a global scope:
var name = "Hello World";
By using that code, any other script on the page attempting to use a variable called name could potentially get an unexpected value of "Hello World" because your script declared it as "Hello World".
By wrapping that code in an anonymous function, you keep the code from conflicting with other variables called name:
(function() {
var name = "Hello World";
})();
In the example above, name is now only available inside of the scope of the anonymous function. It is not global, and therefore cannot conflict with other code on the page.
By wrapping your Angular module in an anonymous function, you prevent your code from conflicting with other code.
Additionally, other people who may use your code won't have to worry about it changing their global scope.
IMHO it's not necessary, even superfluous, as most controllers are already functions:
'use strict';
angular.module('MyApp').controller('AboutController', ['$scope'
function ($scope) {
$scope.title = 'About Us';
}
]);
Everything #nem035 and #tcasey said is correct but it also have another side effect.
If you use tools like Grunt or Gulp it also allow you to have working dists to put in production.
If you do not use Immediate Invoke Pattern you'll most likely have minification problems like:
State X is already defined!
Unknown provider
. . .
I suggest you to wrap all your js modules with this pattern.
I hope I've been helpful.
There are many benefits of you immediately-invoked-function-expression short IIFE and it's best practice to use it. This way each of angular service or controller become isolate and you don't run into global variables as it can happened if you don't use IIFE.
read more about it
Thus far I've worked only with relatively small projects (and mostly alone), but this time I have to collaborate with other programmers... basically because of that I must plan the structure of the website very carefully for the avoidance of spending hours debugging the code.
At this point I suppose doing that in the following manner. I divide my code in modules and store each module in a separate file inside an object (or a function) with a made-up name (lzheA, lzheB, lzheC etc.) to avoid conflicts whether an object with the same name was used in an another piece of code. When the document is loaded, I declare a variable (an object) that I use as a main namespace of the application. Properties of the object are the modules I defined before.
// file BI.lib.js
var lzheA = {
foo: function() {
},
bar: function() {
},
}
// file BI.init.js
function lzheK() {
BI.loadPage();
}
// file BI.loadPage.js
function lzheC() {
var result = document.getElementById('result');
result.innerHTML = "that worked";
}
// and so on
var lzheA,lzheB,lzheD,lzheE,lzheF,lzheG,lzheH,lzheI,lzheJ;
// doing the following when the document is loaded
var BI = {
lib: lzheA,
menu: lzheB,
loadPage: lzheC,
customScripts: lzheD,
_index: lzheE,
_briefs: lzheF,
_shop: lzheG,
_cases: lzheH,
_blog: lzheI,
_contacts: lzheJ,
init: lzheK,
}
BI.init();
https://jsfiddle.net/vwc2og57/2/
The question... is this way of structuring worth living or did I miss something because of lack of experience? Would the made-up names of the modules confuse you regardless of the fact that each one used only twice - while declaring the variable and assigning it to a property?
I consider the namespaces a good option when you want to modularize applications in Javascript. But I declare them in a different way
var myModule = myModule || {}; // This will allow to use the module in other places, declaring more than one specificComponent in other js file for example
myModule.specificComponent = (function(){
// Private things
var myVar = {};
var init = function() {
// Code
};
return {
init: init // Public Stuff
};
})();
If you want to call the init method, you would call it like this
myModule.specificComponent.init();
With this approach, i guarantee that the module will not be overwritten by another declaration in another place, and also I can declare internal components into my namespaces.
Also, the trick of just exposing what you want inside the return block, will make your component safer and you will be encapsulating your code in a pretty way.
Hope it helps
I recently got familiar with the Revealing Module Pattern (RMP) and I've read quite a few articles about it.
It seems like a very good pattern and I would like to start using it in a big project. In the project I'm using : Jquery, KO, requireJS, Jquery Mobile, JayData. It seems to me like it'll be a good fit for the KO ViewModels.
In specific I'd like to use THIS version of it.
One thing I could not find are disadvantages for using this pattern, is it because there aren't any (I find it hard to believe)?
What should I consider before starting to use it?
The Revealing Module Pattern (RMP) creates objects that don't behave well with respect to overriding. As a consequence, objects made using the RMP don't work well as prototypes. So if you're using RMP to create objects that are going to be used in an inheritance chain, just don't. This point of view is my own, in opposition to those proponents of the Revealing Prototype Pattern.
To see the bad inheritance behavior, take the following example of a url builder:
function rmpUrlBuilder(){
var _urlBase = "http://my.default.domain/";
var _build = function(relUrl){
return _urlBase + relUrl;
};
return {
urlBase: _urlBase,
build: _build
}
}
Setting aside the question of why you would use RMP for an object with no private components, note that if you take the returned object and override urlBase with "http://stackoverflow.com", you would expect the behavior of build() to change appropriately. It doesn't, as seen in the following:
var builder = new rmpUrlBuilder();
builder.urlBase = "http://stackoverflow.com";
console.log(builder.build("/questions"); // prints "http://my.default.domain/questions" not "http://stackoverflow.com/questions"
Contrast the behavior with the following url builder implementation
function urlBuilder = function(){
return {
urlBase: "http://my.default.domain/".
build: function(relUrl){ return this.urlBase + relUrl;}
}
}
var builder = new urlBuilder();
builder.urlBase = "http://stackoverflow.com";
console.log(builder.build()); // prints "http://stackoverflow.com/questions"
which behaves correctly.
You can correct the Revealing Module Pattern's behavior by using this scope as in the following
function rmpUrlBuilder(){
var _urlBase = "http://my.default.domain/";
var _build = function(relUrl){
return this.urlBase + relUrl;
};
return {
urlBase: _urlBase,
build: _build
}
}
but that rather defeats the purpose of the Revealing Module Pattern. For more details, see my blog post http://ilinkuo.wordpress.com/2013/12/28/defining-return-object-literals-in-javascript/
I read the article that #nemesv referenced me to (Thanks :)) and I thinks there is one more disadvantage that was not mentioned, so I thought I'd add it here for reference. Here is a quote from the article:
Disadvantages
A disadvantage of this pattern is that if a private function refers to
a public function, that public function can't be overridden if a patch
is necessary. This is because the private function will continue to
refer to the private implementation and the pattern doesn't apply to
public members, only to functions.
Public object members which refer to private variables are also
subject to the no-patch rule notes above.
As a result of this, modules created with the Revealing Module pattern
may be more fragile than those created with the original Module
pattern, so care should be taken during usage.
And my addition:
You can't use inheritance with this pattern. For example:
var Obj = function(){
//do some constructor stuff
}
var InheritingObj = function(){
//do some constructor stuff
}
InheritingObj.prototype = new Obj();
InheritingObj.prototype.constructor = InheritingObj;
This a simple example for inheritance in js, but when using the Revealing Prototype Pattern (archived here) you'll need to do this:
InheritingObj.prototype = (function(){
//some prototype stuff here
}());
which will override you inheritance.
Are there any dangers/caveats one should be aware of when creating JavaScript namespaces?
Our project is fairly expansive and we are running a lot of JavaScript files (20+, expecting more). It is impossible to have any code maintainability without using namespaces, so we are implementing them like so:
var namespace1 = {
doSomething: function() {
...
},
doSomethingElse: function() {
...
}
}
And then to create hierarchies, we link them like so:
var globalNamespace = {
functions1: namespace1,
functions2: namespace2,
...
}
This works fine, but it is essentially a "trick" to make JS behave as if it did have namespaces. Although this method gets used a lot, most literature on this seems to focus on how to do it, and not whether there are any possible drawbacks. As we write more JS code, this is quickly becoming an integral part of the way our system works. So it's important that it works seamlessly.
Were there any situations in which this "induced" namespace system caused you errors, or otherwise needed special attention? Can we safely expect identical behaviour across all browsers?
The way you define namespaces in your example it appears to create globals out of each namespace so you end up with
window.namespace1
window.namespace2
window.globalNamespace
window.globalNamespace.namespace1
window.globalNamespace.namespace2
So if you have anything that clobbers window.namespace1 it will also clobber window.globalNamespace.namespace1
edit:
Here's how we got around this problem:
namespacing = {
init: function(namespace) {
var spaces = [];
namespace.split('.').each(function(space) {
var curSpace = window,
i;
spaces.push(space);
for (i = 0; i < spaces.length; i++) {
if (typeof curSpace[spaces[i]] === 'undefined') {
curSpace[spaces[i]] = {};
}
curSpace = curSpace[spaces[i]];
}
});
}
};
Then you use it like this:
namespacing.init('globalNamespace.namespace1');
globalNamespace.namespace1.doSomething = function() { ... };
This way you don't have to introduce new global variables and you can confidently add to an existing namespace without clobbering other objects in it.
Since you are basically adding functions to objects and those objects into other objects, I would expect each browser to handle this the same way.
But if you want modularity, why not use a (relatively) simple framework like require.js? That will allow you and your team to write code in a modular fashion and allows the team to 'import' these modules where needed:
require(["helper/util"], function() {
//This function is called when scripts/helper/util.js is loaded.
});
Require.js will take care of dependencies, and it will also prevent polluting the global namespace.
We use a similar system at work and it does the job just fine. I don't see any drawbacks there could be; it's just objects and properties. For that same reason, cross browser compatibility should be good. You can end up having to write some long names to resolve to a particular function, like Foo.Bar.Test.Namespace2.Function, but even then that can be solved by assigning it to a variable before hand.
This is how I'd recommend doing it, so you stay out of the global scope entirely except for your "base" namespace. We do something similar where I work. Let's say you work for Acme co, and want ACME to be your base namespace.
At the top of every file, you'd include:
if (!window.ACME) { window.ACME = {} }
Then you just go and define whatever you want in terms of that.
ACME.Foo = {
bar: function () { console.log("baz"); }
}
If you want a deeper level of namespace, you just do the same thing for each level.
if (!window.ACME) { window.ACME = {} }
if (!ACME.Foo) { ACME.Foo = {} }
This way each file can be tested independently and they'll set up the namespace infrastructure automatically, but when you compile them together or if you test multiple files simultaneously, they won't keep overwriting things that are already defined.
I have worked with oop style scripting before and trying to get some kind of system with javascript. I wanted to try the most basic pattern, Constructor Pattern.
So I setup one js file called ImageView with a constructor matching the name of the js file.
function ImageView(){
alert( 'this is working');
}
Then I set up another js file called Main.js which will be the main instantiation class.
$(document).ready(function(){
var imageViewer = new ImageView();
//ImageView();
});
Now what I don't get is I can call this object ImageView without even the new constructor call. For example ImageView(). From what I gather this is just another global function and not a encapsulated class. I'm trying to get away from global crap and separate my methods and properties to their own class. What am I missing her.
Others have already answered what the difference is between using new and not using it, so I'll answer your entirely separate question: how do I avoid globals in JS?
The answer is that you can't entirely. You will always have at least one, in which you can stuff your other stuff. So for example if you wanted a "namespace" of xyz, you would do:
// global:
var xyz = {}; // or, window.xyz = {} if you are in a browser and want to be more explicit.
// "encapsulated" within the xyz "namespace":
xyz.ImageView = function () { alert("This is working"); };
There is a better solution: use the emerging concept of JavaScript modules. These are not language features (at least not in the current version of JavaScript), so they are really just hacks introduced by very clever libraries that overwrite a couple of global variables to let you avoid creating any more than the ones provided by those libraries. A good example is RequireJS, where you could do something like the following:
// In xyz.js, define the xyz module (name automatically derived from filename).
// Whatever is returned from the function you pass to define is "the xyz module"
define(function () {
return {
ImageView: function () { alert("This is working"); }
};
});
// In other code, in a different file, you can say "I require the xyz module
// to do my work," and pass require a function saying "once you've got the xyz module
// for me, here's the work I will do with it".
require(["xyz"], function (xyz) { // dependency array maps to callback arguments
// I got the xyz module, including the ImageView function it exported. Use it!
var imageViewer = new xyz.ImageView();
});
Here the clever globals RequireJS introduces are the functions define and require, but if you use them right, you can avoid ever introducing any further globals beside those two.
Inside of ImageView, the value of this will be different if you call it with new. Without, it's just another function. With new it will create a new ImageView instance and bind it to the variable this.
First off JavaScript doesn't have built in namespaces. It can only be simulated. You must also include each javascript file you plan on using.
Your right about just calling ImageView() that basically invokes the constructor on this which is next level of scope.
Using new ImageView() creates a new Object of constructor ImageView and this points to the new instance.
JavaScript is a prototype language with loose typing.