I am a little confused here. Following the module pattern in JS, a module is normally a returned object from an anonymous function that is immediately executed. But what if I don't want to execute the function and instead call it whenever I need to e.g. window.onload.
var module = function (args) {
//private members
return {
//public members
};
};
var module_instance = module (args); // module instance or facade instance?
Are there any problems with this implementation? Is there a different, more efficient way to do this?
Also, following the previos block of code, what if I call the function again and asign the returned value to another variable:
var module_instance2 = module (args);
does that mean I now have a 2nd facade of the function or is it a new function altogether?
Cheers!
That function is the constructor of your module so each time you call that function, a new separate instance of the module is created and assigned to the receiving variable.
There is not any problem with this implementation (actually it is very common,), and you can use it wherever in your program to obtain a new instance of that module.
Best.
The module pattern is similar to namespaces in other languages, and is used to prevent global variable pollution and as a method of encapsulation.
window.module1 = (function() {} {
var version = "0.0.1";
function func1 () {};
function func2 () {};
return = {
version: version,
func1: func1,
func2: func2,
};
})()
You could have a Function DeclareModule() that defines a module on the window object.
var DeclareModule = function(name, content) {
if (typeof content === 'object') {
window[name] = content;
} else if (typeof content === 'function') {
window[name] = content();
}
};
//Declared by object
DeclareModule("module1", {
version: "0.0.1",
func1: function () {},
func2: function () {}
});
//Declared by function
DeclareModule("module1", function () {
var version = "0.0.1";
function func1 () {};
function func2 () {};
return {
version: version,
func1: func1,
func2: func2
};
});
Have a look at AMD and CommonJS modules, or an article by Addy Osmani.
Related
Could you explain to me what is the difference between that two approaches (FirstModule and SecondModule:
var MyModule = (function () {
return {
method: function () {
console.log("MyModule:method");
}
}
})();
var FirstModule = (function () {
return {
test: function () {
MyModule.method();
}
}
})();
var SecondModule = (function (myMethod) {
return {
test: function () {
myMethod.method();
}
}
})(MyModule);
In both cases we have the same object, it isn't a copy. I would be grateful for any good information, advantages, disadvantages of any approach.
The first approach uses the MyModule variable, which can be overwritten by other code, outside the module, after the FirstModule value has been asigned.
The second uses the myMethod variable, which can't (although properties of the object assigned to myMethod still can because that object is still globally available via the MyModule variable).
Which one do you prefer and what are pros & cons one over another ?.
Personally i found singleton hard to read and maintain, a lot of context changes(this), always ends with caching right context through var self = this (or some proxy like $.proxy) + i will always have one global variable(singleton), while in second approach i can avoid creating global variable if module doesn't need to expose any API.
Simple example: (User click on "add to cart", some ajax get triggered and on success html(notification) is created)
Html
<div class="cart">
Add to cart
</div>
Module pattern
Not truly module pattern by definition, because i'm not returning anything from it, click handler can access outer scope via closure.
;(function(window, $, undefined) {
function constructHtml(data) {...}
function addToCart(product_id, quantity) {
...
$.ajax({
...
success: function(data) { constructHtml(data); }
});
}
$(function() {
var $addBtn = $('div.cart a');
var productId = $addBtn.data('product-id');
$addBtn.click(function(e) {
e.preventDefault();
addToCart(productId);
});
});
})(this, jQuery);
Singleton - Object literal(same example)
var Cart = {
settings: {
$addBtn: $('div.cart a'),
productId: $('div.cart a').data('product-id')
},
init: function() {
this.bindUiActions();
},
bindUiActions: function() {
var self = this;
this.settings.$addBtn.click(function(e) {
e.preventDefault();
self.addToCart(self.settings.productId);
});
},
addToCart: function(product_id, quantity) {
...
var self = this;
$.ajax({
...
success: function(data) {
self.constructHtml(data);
}
});
},
constructHtml: function(data) {...}
};
Cart.init();
While Singleton vs. Module Pattern can be a legitimate question, with the example you gave, this question should be reworded as Singleton vs IIFE, as it's not the module pattern per se, but rather the IIFE that the module pattern is wrapped in that is keeping cruft out of your Cart singleton. And even then, it's not a vs. kind of question -- both IIFE and Singleton can be used together. The purpose of the IIFE is just to keep stuff out of global scope.
So ..., you can package your singleton Code into an IIFE as follows
;(function(){
var Cart = {
settings: {
// Your code ...
};
Cart.init();
})();
In this case, you're writing your code as a Singleton but wrapping it in an IIFE, and there is no usage of global scope. The IIFE is completely independent of how you choose to write and organize your code. You would need a different example for a Singleton vs. Module Pattern question.
IIFE (immediately invoked function expression):
(function() {
console.log('run this in your browser console')
})()
Module pattern:
var module = (function () {
var privateScopeVar = 1 // scope of the IIF
// the 'this' context in this scope is the global object (e.g. window)
// returns literal object who's method's scopes are lexically bound
// to the IIF scope
return {
publicMethod: () => privateScopeVar // publicMethod scope can access IIF scope
}
})()
Singleton Literal + Singleton Literal that cannot be overwritten if included/imported more than once in EcmaScrip5:
var singleInstance = { firstName: 'Greg' }
var singleInstance = singleInstance || { firstName: 'Greg' }
Singleton Literal that cannot be overwritten or initialized more than once in EcmaScrip6:
const singleInstance = {
firstName: 'Greg',
called: false,
init: () => {
if (!this.called) {
console.log('only once')
this.called = true
}
}
}
// of course singleInstance.called = false; singleInstance.init() is always possible
Singleton inside IIF (provides private state)
const singleton = (function () {
// IIF private scope ensures there is a single instance ever
var storedInstance
// Also some private state for the singleton instance as well
const firstName = 'Greg'
// literal object that holds constructor function
const Singleton = {
getInstance: () => {
if (!storedInstance) {
storedInstance= {
getName: () => firstName
}
}
return storedInstance
}
}
return Singleton
})()
I have a file stats.js.
It's contents are
(function () {
func1 = function () {
}
func2 = function () {
}
module.exports = this;
}).call(this);
Alegedly, when I do
var stats = require("./stats");
I should be able to get func1 and func2 with stats.func1, stats.func2, right?
Well, I can't. The stats object is just empty. A few traces in the stats.js revealed that "this" is also an empty object.
What gives?
First and foremost see this link.
Now lets see your code -
var stats = require("./stats");
//My steps -
//First Log
console.log(stats.func1); // returns undefined
//Second Log
console.log(global.func1, global === GLOBAL); // returns [Function], true
Take aways from this code -
1. In the browser the global object is window object.
2. In node.js it is the global object.
3. Defining something using var in a module will only create a variable with a module scope.
4. Defining something without the var keyword will create a variable in the global scope.
So func1 and func2 were defined in the global scope. Passing this to module.exports will pass the current module object only.
hope it helps, happy coding!
No it shouldnt? That format is nothing like what Node.js needs in order to do its job.
"What gives" is that you didn't read up on how node works. Node.js isn't just "JavaScript", it's a proramming model with a much richer API and specific behaviours. Requires use the "module.exports" object, so it would be a good idea to actually read up on how to use node.
mything.js:
var func3 = function() { ... },
prop = "something";
...
module.exports = {
func1: function() { ... },
func2: function() { ... },
func3: funct3,
prop: prop,
...
};
which is identical to:
var func3 = function() { ... },
prop = "something",
...
MyLib = {
func1: function() { ... },
func2: function() { ... },
func3: funct3,
prop: prop,
...
};
...
module.exports = MyLib;
app.js:
var mything = require("mything);
Let's say I am writing code at the main page level and 2 dependencies require the same instance of an object and also state that as a dependency. What is the appropriate way to go about this?
Basically what I want to do is say, "If this dependency isn't loaded... then load it. Otherwise, use the same instance that was already loaded and just pass that one."
You would make that a module-level variable. For example,
// In foo.js
define(function () {
var theFoo = {};
return {
getTheFoo: function () { return theFoo; }
};
});
// In bar.js
define(["./foo"], function (foo) {
var theFoo = foo.getTheFoo(); // save in convenience variable
return {
setBarOnFoo: function () { theFoo.bar = "hello"; }
};
}
// In baz.js
define(["./foo"], function (foo) {
// Or use directly.
return {
setBazOnFoo: function () { foo.getTheFoo().baz = "goodbye"; }
};
}
// In any other file
define(["./foo", "./bar", "./baz"], function (foo, bar, baz) {
bar.setBarOnFoo();
baz.setBazOnFoo();
assert(foo.getTheFoo().bar === "hello");
assert(foo.getTheFoo().baz === "goodbye");
};
Just provide an API for your singleton as you would.
And make sure its lazily loaded. The easiest way is to use an abstraction library like underscore that supplies cross browser helpers. Other options are ES5 Object.defineProperty or custom getter/setters.
In this case _.once ensures that constructor's result is cached after the first call, it basically lazy loads it.
define(function() {
var constructor = _.once(function() {
...
});
return {
doStuffWithSingleton: function() {
constructor().doStuff();
}
};
});
_.once from underscore.
Combining Raynos's concerns about encapsulation with the OP's clarification that he wants to expose a couple of methods on a messaging service, this is I think the right way to go about it:
// In messagingServiceSingleton.js
define(function () {
var messagingService = new MessagingService();
return {
notify: messagingService.listen.bind(messagingService),
listen: messagingService.notify.bind(messagingService)
};
});
// In bar.js
define(["./messagingServiceSingleton"], function (messagingServiceSingleton) {
messagingServiceSingleton.listen(/* whatever */);
}
// In baz.js
define(["./messagingServiceSingleton"], function (messagingServiceSingleton) {
messagingServiceSingleton.notify(/* whatever */);
}
Function.prototype.bind will not be present in all browsers, so you would need to include a polyfill like the one Mozilla provides.
An alternate (and in my opinion probably better) approach would be to make the messaging service object itself a module. This would look something like
// In messagingService.js
define(function () {
var listenerMap = {};
function listen(/* params */) {
// Modify listenerMap as appropriate according to params.
}
function notify(/* params */) {
// Use listenerMap as appropriate according to params.
}
return {
notify: notify
listen: listen
};
});
Since you expose the same notify and listen methods to everyone who uses your module, and those always refer to the same private listenerMap variable, this should do what you want. It also obviates the need for Function.prototype.bind, and gets rid of the rather-unnecessary distinction between the messaging service itself and the module which enforces singleton usage of it.
Here's a version where the module itself is the shared variable instead of a variable within that module.
define('foo', [], {bar: "this text will be overwritten"});
define('bar', ["foo"], function (foo) {
return {
setBarOnFoo: function () { foo.bar = "hello"; }
};
});
define('baz', ["foo"], function (foo) {
return {
setBazOnFoo: function () { foo.baz = "goodbye"; }
};
});
require(["foo", "bar", "baz"], function (foo, bar, baz) {
bar.setBarOnFoo();
baz.setBazOnFoo();
$('#results').append(foo.bar + ' ' + foo.baz);
});
// reads: hello goodbye
As a variation of Domenic's answer, you can use the 'exports' magic module to automatically generate a reference for the module -- "Properties added to the exports object will be on the public interface of the module, no need to return any value." This avoids having to call the getTheFoo() function to obtain a reference.
// In foo.js
define(['exports'], function (foo) {
foo.thereCanBeOnlyOne = true;
});
// In bar.js
define(["exports", "./foo"], function (bar, foo) {
bar.setBarOnFoo = function () { foo.bar = "hello"; };
});
// in baz.js
define(["exports", "./foo"], function (baz, foo) {
baz.setBazOnFoo = function () { foo.baz = "goodbye"; };
});
// In any other file
define(["./foo", "./bar", "./baz"], function (foo, bar, baz) {
bar.setBarOnFoo();
baz.setBazOnFoo();
assert(foo.bar === "hello");
assert(foo.baz === "goodbye");
assert(foo.thereCanBeOnlyeOne);
});
To address the comment below, I personally have found the above convention to be useful. Your mileage may vary, but feel free to adopt the convention if you think it is useful. The convention boils down to these two rules:
Declare 'exports' as the first dependency in the define array.
Name the parameter in the function after the JavaScript file.
Using the name of file, e.g. for foo.js name the variable 'foo', increases the readability of the code as most developers will define 'foo' as the parameter for the foo.js dependency. When scanning the code or using grep, it is easy to find all references to 'foo' use both inside and outside the module and it makes it easy to pick out what the module is exposing to the public. For example, renaming bar.setBarOnFoo to bar.setFooBar is much easier if the declaration in the bar.js module mirrors the usage in other files. A simple search and replace of bar.setBarOnFoo to bar.setFooBar across all files will accomplish the task.
I was in this scenario:
For different reasons I needed to call a function that was on a requirejs module, but the click that fired that call was out of require.
The way I fixed this was creating a requirejs modure that writes over the window object.
define("one", [], function() {
window.popupManager = (function () {
console.log ('aca');
var popUpManager = function () {
self = this;
self.CallMe = function ()
{
alert ('someone calls');
};
};
return new popUpManager();
})();
});
require(['one']);
window.popupManager.CallMe();
This way if any piece of code that is out of the require spectrum (I know it shouldn't be this way) can call functions of this require that writes over the window object.
I really know this is not an "elegant" solution, but it may help you in case of an emergency.
I'm always learned to define a function in JavaScript like this:
function myFunction(arg1, arg2) { ... }
However, I was just reading Google's guide to Javascript, it mentioned I should define methods like this:
Foo.prototype.bar = function() { ... };
Question: Is "Foo" in the example an Object, or is it a namespace? Why isn't the Google example the following code (which doesn't work):
prototype.bar = function() { ... };
UPDATE: In case it helps to know, all of my JavaScript will be called by the users browser for my web-application.
Your two examples are not functionally equivalent. The first example simply defines a function (probably a global one, unless you define it inside another function). The second example extends the prototype of a constructor. Think of it as adding a method to the class Foo.
Unless you're building a JavaScript library, my suggestion would be to use neither and use some kind of namespace system. Create a single global object that acts as a namespace through which you can access all your functions.
var MyObject = {
utils: {
someUtil: function() {},
anotherUtil: function() {}
},
animation: {
// A function that animates something?
animate: function(element) {}
}
};
Then:
// Assuming jQuery, but insert whatever library here
$('.someClass').click(function() {
MyObject.animation.animate(this);
});
If you want to emulate classes in JavaScript, you would define the "class" as a function (the function itself being the constructor) and then add methods through the prototype property.
function Foo() {
// This is the constructor--initialize any properties
this.a = 5;
}
// Add methods to the newly defined "class"
Foo.prototype = {
doSomething: function() { /*...*/ },
doSomethingElse: function() { /*...*/ }
};
Then:
var bar = new Foo();
console.log(bar.a); // 5
bar.doSomething();
// etc...
I'm always learned to define a function in JavaScript like this:
function myFunction(arg1, arg2) { ... }
There are two ways to define a function. Either as a function declaration
function foo(...) {
...
}
Or as a function expression
var foo = function() {
...
};
Read more here.
However, I was just reading Google's guide to Javascript, it mentioned I should define methods like this: Foo.prototype.bar = function() { ... };
This is specifically related to method creation for objects, not just normal, stand-alone functions. Assuming you have the base object declaration:
var Foo = function() {
...
};
Just like any other assignment, to assign a function to an object's property, you must use an assignment expression. You can do this two ways. The succinct and common way (as suggested by Google's reference)
Foo.prototype.bar = function() {};
Or, if you want to continue to use the declarative form of defining functions
function bar() {
...
};
Foo.prototype.bar = bar;
This is normally more verbose than necessary, but may be useful in situations where you want to assign the same method to multiple object prototypes.
Question: Is "Foo" in the example an Object, or is it a namespace? Why isn't the Google example the following code (which doesn't work): prototype.bar = function() { ... };
Foo is an object. Although the concept can be expressed through the use of static objects, as I've shown in my answer to your other question, there is no such thing as namespaces in JavaScript. Further, especially in the example code given, Foo is likely intended to be an instantiated object, which precludes it from being behaving like a namespace.
Of course it doesn't work: prototype has not been defined as an object (unless, of course, you define it as such). The prototype property exists on every object (a function is also an object), which is why you can do Foo.prototype.bar = ...;. Read more here.
=====> 2017 Update <=====
This question and answers is 7 years old and is very outdated. This answer includes new syntax for versions of ES5, ES6, and compatible with ES7.
Best way to define a function?
There is no one "Best" way to define a function. How you define the function is dependent on the intended use and lifetime of the function.
Global functions
Defined as a statement with the function token followed by the function name with lowercase camelcase
function functionName (arguments) {
// function body
}
is preferable over the function expression...
var functionName = function (arguments) {
// function body
}
...as the assignment to the variable of the function does not occur until the defining line is executed. Unlike the prefered method which is available immediately after parsing before any code is executed.
const functionName = function(arguments){/*function body*/}
var functionName = function functionName(arguments){/*function body*/}
var functionName = function functionAltName(arguments){/*function body*/}
Function objects
As a function statement with uppercase camelcase function name
function MyObjectFunction (arguments) {
/*function body*/
// if this function is called with the new token
// then it exits with the equivalent return this;
}
const obj = new MyObjectFunction(foo);
Anonymous function expression.
A common practice is to create object via an immediately invoked function that has no name (and is hence anonymous)
;(function (arguments) { /*function body*/ } ("argument val"))
Or
;(function(arguments){ /*function body*/ })("argument val")
NOTE the inclusion of the ; befor the function. This is very important as the open "(" will prevent automatic semicolon insertion on any code above the function.
Immediately invoked function expression.
const functionResult = (function (arguments) {
/*function body*/
return functionResult;
}());
const functionResult = (function (arguments) {
/*function body*/
return functionResult;
})();
As a var or block scopedconst, let
Anonymous callback.
With ES6 you should use the arrow function syntax rather than anonymous function expressions.
myArray.forEach((item,i) => {/*function body*/});
myArray.filter(item => !item);
setTimeout(() => {/*function body*/}, 1000);
Function as properties.
Using the object declaration function shorthand syntax.
var myObj = {
functionName (arguments) {/*function body*/},
}
// called
myObj.functionName("arg");
is preferable over
var myObj = {
functionName : function (arguments) {/*function body*/},
}
Or via function object declarations
function MyObjectFunction(arguments){
this.propertyFunction = function(arguments) { /*function body*/ }
// or arrow notation is fine
this.propertyFunction = (argument) => { /*function body*/ };
}
Functions as prototypes
function MyObj (arguments) {
MyObj.prototype.functionName = function(arguments) { /*function body*/ }
}
or
function MyObj (arguments) {}
MyObj.prototype.functionName = function(arguments) { /*function body*/ }
or
MyObj.prototype = {
functionName(arguments) { /*function body*/ }
}
Defining a prototype function is useful when creating constructors or 'classes' in JavaScript. e.g. a func that you will new
var MyClass = function(){};
MyClass.prototype.doFoo = function(arg){ bar(arg); }
but is of no use in plain old library functions e.g.
function doPopup(message){ /* create popup */};
There are several benefits of using a prototype function including but not limited to
speed
memory usage
extensibility
But, again, this is in the context of creating constructors for instantiable 'classes'
HTH
It works like so:
(function(){ // create an isolated scope
// My Object we created directly
var myObject = {
a: function(x,y) {
console.log('a');
},
b: function(x,y) {
console.log('b');
this.a(x,y);
}
};
})();
(function(){ // create an isolated scope
// Create a Object by using a Class + Constructor
var myClass = function(x,y) {
console.log('myClass: constructor');
this.b(x,y);
};
myClass.prototype = {
a: function(x,y) {
console.log('myClass: a');
},
b: function(x,y) {
console.log('myClass: b');
this.a(x,y);
}
};
// Define a function that should never inherit
myClass.c = function(x,y) {
console.log('myClass: c');
this.a(x,y);
};
// Create Object from Class
var myObject = new myClass();
// Will output:
// myClass: constructor
// myClass: b
// myClass: a
// Define a function that should never inherit
myObject.d = function(x,y) {
console.log('myObject: d');
this.a(x,y);
};
// Test the world is roung
console.log(typeof myClass.c, 'should be undefined...');
console.log(typeof myClass.d, 'should be function...');
})();
(function(){ // create an isolated scope
// If you are using a framework like jQuery, you can obtain inheritance like so
// Create a Object by using a Class + Constructor
var myClass = function(x,y) {
console.log('myClass: constructor');
this.b(x,y);
};
myClass.prototype = {
a: function(x,y) {
console.log('myClass: a');
},
b: function(x,y) {
console.log('myClass: b');
this.a(x,y);
}
};
// Create new Class that inherits
var myOtherClass = function(x,y) {
console.log('myOtherClass: constructor');
this.b(x,y);
};
$.extend(myOtherClass.prototype, myClass.prototype, {
b: function(x,y) {
console.log('myOtherClass: b');
this.a(x,y);
}
});
// Create Object from Class
var myOtherObject = new myOtherClass();
// Will output:
// myOtherClass: constructor
// myOtherClass: b
// myClass: a
})();
(function(){ // create an isolated scope
// Prototypes are useful for extending existing classes for the future
// Such that you can add methods and variables to say the String class
// To obtain more functionality
String.prototype.alert = function(){
alert(this);
};
"Hello, this will be alerted.".alert();
// Will alert:
// Hello, this will be alerted.
})();
Edit: Fixed code so that it will actually run in your browser if you copy and paste :-)
Foo is both an Object and a namespace. See this question.
Using objects as namespaces prevents name collisions. That's always a good idea, but especially when you're developing and/or using shared libraries.
If you don't expect to be making multiple Foo objects (and so don't need the object-oriented style), you could create your functions as methods on a singleton object:
var Foo = {}
Foo.bar = function() { ... }
or
var Foo = {
bar: function() {...},
quux: function() {...}
};
You'd then simply call the function as:
Foo.bar()
(This kind of declaration is roughly equivalent to a static method in C++ or Java.)