Conside the following JavaScript code. The function definitions all seem to achieve the same thing. Is there any recommended convention for defining the functions which are then 'revealed' in the return dictionary object?
var testModule = (function(){
var counter = 0;
var localFunc1 = function() {
return "local 1";
}
function localFunc2() {
return "local 2";
}
this.localFunc3 = function() {
return "local 3";
}
localFunc4 = function() {
return "local 4";
}
return {
proxy1: localFunc1,
proxy2: localFunc2,
proxy3: localFunc3,
proxy4: localFunc4
};
})();
I don't think that there is any real preferred method. The most common setup I've seen involves creating all of your methods as local (using var) then returning an object that exposes the public methods.
A couple of things to note:
this.localFunc3 will only work if your object is instantiated with the 'new' keyword
when returning your object, remove the () from each function so that you are returning a reference to the function and not the function's returned value
localFunc4 will be global since it has no 'var' keyword in front of it
When working with a module pattern like this, I tend to go for something along the lines of:
var Obj = ( function () {
var private_static = 'this value is static';
return function () {
//-- create return object
var _self = {};
//-- create private variables
var private_variable = 'this value is private';
var func1 = function () {
return 'value 1';
};
//-- attach public methods
_self.func1 = func1;
//-- return the object
return _self;
};
} )();
Some notes about this method:
allows for private static variables (if you don't need private static variables, you can remove the closure)
by creating the _self reference first, you can pass a self reference to any objects instantiated from within that need a reference to their parent
I like that I can reference all internal functions without _self.whatever or this.whatever, ignoring whether or not they are private or public
The definitions do not achieve the exact same thing.
var localFunc1 and function localFunc2 do the same thing, they create functions only available inside your outer function.
this.localFunc3 and localFunc4 are not really local functions: they both belong to the window object (this in that context is window, and localFunc4 is declared without the var statement).
So, the latter two don't even need to be exposed on your returned object, since they're already global. And, actually, you are not exposing any functions on your return object, you are exposing their return values, since you invoke each of them. Were you trying to do this?
return {
proxy1: localFunc1,
proxy2: localFunc2,
proxy3: localFunc3,
proxy4: localFunc4
};
Note: I recommend you watch this video where Douglas Crockford explains the multiple ways to deal with inheritance in JavaScript. I believe you are looking for what he calls "parasitic inheritance".
Related
I am trying to wrap my head around different Module pattern declinations. I see different ways of writing these modules and exposing their data.
I'm expecting information on advantages/disadvantages, better patterns not described here, use cases for each of them.
A) Object literal wrapped in a self invoking function, firing off with an init method: (source)
(function() {
var MyModule = {
settings: {
someProperty: 'value';
}
init: function() {
someMethod();
}
someMethod: function() {
// ...
}
};
MyModule.init();
})();
This is an example of a simple "Tweet This" utility I built. Am I using this pattern correctly? So far it's the only one that I have actual experience in writing.
B) Module as a namespaced self-invoking anonymous function: (source)
var MyModule = (function () {
var MyObj = {}
function privateMethod() {
// ...
}
MyObj.someProperty = 1;
MyObj.moduleMethod = function () {
// ...
};
return MyObj;
}());
Are there any advantages/disadvantages over the previous style? Also, what would be the implications of using object literal notation here instead of the dot syntax in the example? Object literal seems cleaner and easier, but I'm not really aware of the proper use cases for each?
C) Module as a namespaced self-invoking anonymous function, but only exposing desired results through a return block: (source)
var MyModule = (function() {
var myPrivateVar, myPrivateMethod;
myPrivateVar = 0;
myPrivateMethod = function(foo) {
console.log(foo);
};
return {
myPublicVar: "foo",
myPublicFunction: function(bar) {
myPrivateVar++;
myPrivateMethod(bar);
}
};
})();
Similar to the previous style, but instead of exposing an entire object with all of it's properties/methods, we're just exposing specific bits of data through a return statement.
D) Module as a function wrapped in a self-invoking anonymous function, with nested functions acting as methods. The module is exposed through the window object, then constructed via the new keyword: (source)
(function(window, undefined) {
function MyModule() {
this.myMethod = function myMethod() {
// ...
};
this.myOtherMethod = function myOtherMethod() {
// ...
};
}
window.MyModule = MyModule;
})(window);
var myModule = new MyModule();
myModule.myMethod();
myModule.myOtherMethod();
I'm assuming the strength of this pattern is if the module is a 'template' of sorts where multiple entities may need to exist within an application. Any specific examples of a good use case for this?
All of these are using the same pattern just in slightly different ways.
A) Object literal wrapped in a self invoking function, firing off with an init method:
This is fine if you don't intend to allow anyone else to access a chunk of code. You don't even have to have an init function. Wrapping your code in an IIFE (immediately invoked function expression) prevents global namespace pollution and allows the use of "private" variables. In my opinion, this is just good practice, not a module.
B) Module as a namespaced self-invoking anonymous function:
This is what people mean when they're talking about the module pattern. It gives you private variables and functions then exposes those through a public interface. That interface just so happens to be called MyObj in your example.
C) Module as a namespaced self-invoking anonymous function, but only exposing desired results through a return block:
This is actually exactly the same thing a B. The only difference is that methods on the interface can't directly reference the interface itself like you can in B. Example:
MyObj.methodA = function() {
return MyObj.methodB();
};
That will work with the previous example because you have a name to reference it but is only useful when you expect public methods to be called using anything other than the returned object as the execution context. i.e, setTimeout(MyModule.methodA) (that will be called with the global context so this.methodB() would not work as intended.
D) Module as a function wrapped in a self-invoking anonymous function, with nested functions acting as methods. The module is exposed through the window object, then constructed via the new keyword:
Same thing as the previous 2 except for 2 minor differences. window is passed as an argument because it has historically been true that it's faster to access a local variable than a global variable because the engine doesn't have to climb up the scope chain. However, most JS engines these days optimize accessing window since it's common and a known object. Likewise, undefined is given as a parameter with nothing passed as an argument. This ensures you have a correct undefined value. The reasoning behind this is that technically, you can assign any value to undefined in non-strict mode. Meaning some 3rd party could write undefined = true; and suddenly all of your undefined checks are failing.
The other difference is that you're returning a function instead of an object. The bonus behind this is that you can have private variables which are shared in each instance of an object, as well as private variables per instance. Example:
var count = 0;
function MyObject(id) {
var myID = id;
count++;
// Private ID
this.getID = function() {
return myID;
};
// Number of instances that have been created
this.getCount = function() {
return count;
};
}
The downside to this is that you aren't attaching methods to the prototype. This means that the JS engine has to create a brand new function for every single instance of the object. If it was on the prototype, all instances would share the same functions but could not have individual private variables.
I've got 3 codes :
var control = new Control();
function Control() {
this.doSomethingElse = function() {...}
this.doSomething = function () {
control.doSomethingElse();
}
}
Or
var control = new Control();
function Control() {
var self = this;
this.doSomethingElse = function() {...}
this.doSomething = function () {
self.doSomethingElse();
}
}
Or
var control = Control();
function Control() {
var self = this;
this.doSomethingElse = function() {...}
this.doSomething = function () {
self.doSomethingElse();
}
return self;
}
Important : The function is a controller, and just declared once. Then I'm using "control" everywhere in my code...
I was wondering if the control.doSomethingElse() was slow ?
In the end, what is the right thing to do and/or the fastest code in those exemple ?
Thanks !
The first is wrong - an object should never internally use the variable name by which it is known outside. Other code could change that variable to point to something else, breaking this code.
The third is also wrong - when calling Control() without new the assignments to this.foo inside will end up getting attached to the global object (except in strict mode, where there's no implicit this on bare function calls, so the assignment to this.doSomethingElse tries to attach to undefined, causing a runtime error).
That only leaves the second as appropriate, but ultimately it's a question of correctness, not performance.
Do not define methods in constructor - that means defining them every time an instance is created. Use Control.prototype.foo = function() {} instead. Also you do not need to return this if you're using new operator - that's the whole point of new operator.
The recommended approach is this:
function MyClass(param1) {
// Here we're changing the specific instance of an object
this.property1 = param1;
}
// Prototype will be shared with all instances of the object
// any modifications to prototype WILL be shared by all instances
MyClass.prototype.printProperty1 = function() {
console.log(this.property1);
}
var instance = new MyClass("Hello world!");
instance.printProperty1(); // Prints hello world
To understand this code, you need to understand javascript's prototype-based inheritance model. When you create instance of MyClass, you get a new object that inherits any properties present in MyClass.prototype. Read more about it.
Also I wonder:
The function is a controller, and just declared once.
If you're not using this multiple times, you don't need to create something like class. You can do this instead:
var control = {doSomething:function() { ... }};
I assume you are used to Java, where everything must be a class, whether it makes sense or not. Javascript is different, you can also make single objects or functions as you need.
In JavaScript, classes are usually emulated through constructors. However, I'm curious as to how one can create an encapsulated class, i.e. a class that keeps some of it's members private.
The commonly seen way of creating a 'class' is as follows:
function MyClass(parameter) {
this.value = parameter;
}
MyClass.prototype.myPublicFunction = function() {
console.log("About to run private function.");
myPrivateFunction();
};
MyClass.prototype.myPrivateFunction = function() {
...
};
As you can see, in this example myPrivateFunction is actually public. One approach I've seen to solve this problem is the following:
function MyClass(parameter) {
this.value = parameter;
this.myPublicFunction = function() {
console.log("About to run private function.");
myPrivateFunction.call(this);
}
function myPrivateFunction() {
...
}
}
This works; myPrivateFunction is inaccessible from the outside. But this approach has a problem - all functions in this 'class' are going to be copied across instances, instead of shared through the prototype. Also using privateFunction.call(this) everywhere isn't awesome.
Same goes for non-function members. How can I define a private instance-member in a class? What is the best and what is the most common approach? Is it acceptable to simply rely on a naming convention (such as beginning private function names with a _)?
You could create a scope to hide you private functions with an auto executing function.
Like:
(function(){
function myPrivateFunction(arg_a, arg_b) {
/* ... */
console.log("From priv. function " + this.value);
}
window.MyClass = function(parameter) {
this.value = parameter;
this.myPublicFunction = function() {
console.log("About to run private function.");
myPrivateFunction.call(this, 'arg_a', 'arg_b');
}
}
})();
But then you need to use MyClass only after it is declared since now it is an function expression and not a function statement, but all instances of MyClass will share the same instance of myPrivateFunction. but you will need to use Function.prototype.call (as in myPrivateFunction.call(this, 'arg_a', 'arg_b'); to get the value of this keyword to match your instance.
If you do just myPrivateFunction('arg_a, 'arg_b'); the keyword this will point to the global object (window on browsers) or null if 'strict mode' is enabled.
Just a note: In my own code I don't do this but rely on naming conventions like MyClass.prototype._myPrivateFunction = function(){}; when not using some framework.
I've tried two ways to declare a member function in JS:
function init() {
var name = "Mozilla";
function displayName() {
alert(name);
}
}
a = new init();
a.displayName()
And
function init() {
var name = "Mozilla";
displayName = function() {
alert(name);
}
}
a = new init();
a.displayName()
The first method told me that displayName() is undefined. The way I see it a variable of type Function with name displayName is created, and thus it should work.
Any one care to explain why it didn't work?
It doesn't work because that's now how JavaScript works. Just declaring a function within a constructor function doesn't set it up on the object created by the constructor function, you have to make the link between the object and the function explicitly (directly by assigning it to the object, or more often indirectly via a prototype).
The typical way you do that is via prototypical inheritance, although you can also just assign functions directly to individual objects (more below — but you talked about "member functions," and the typical way you do things like that in JavaScript is via prototypes).
There are a couple of ways to set up prototypical inheritance. The classic way, which is compatible with a broad range of JavaScript engines even in legacy browsers, is via the prototype property on constructor functions, which refers to an object. That object becomes the prototype of instances created via new FunctionName. You add properties to that object to share them amongst the instances created by that function.
So, using prototypical inheritance:
function Init(name) {
this.name = name;
}
Init.prototype.displayName = function() {
alert(this.name);
};
var i = new Init("Mozilla");
i.displayName();
Notes on the above:
In JavaScript, the overwhelming convention is that constructor functions start with an upper case letter. So I called it Init rather than init.
All functions automatically have a prototype property on them, which is a blank object.
I add a property to that object called displayName which refers to a function.
Rather than hard-coding the name, I pass it into Init as an argument.
Note that I store the name on a property on the newly-constructed instance; within the call to Init, that instance is available as this.
Similarly, because displayName is called as part of an expression retrieving the function reference from the object, this is the object within the call to displayName, and so this.name has the name.
To keep things simple in the above, I assigned an anonymous function to displayName. (The property has a name, the function does not.) I tend not to do that in real code.
All instances constructed via new Init will share the same copy of the displayName function, via the prototype.
More to explore (on my blog):
Mythical methods
You must remember this
Anonymouses anonymous
You might also be interested in my Lineage toolkit, if you're interested in building classes of objects in JavaScript (and hierarchies).
As of ES5, there's another option: Object.create. This allows you to create objects and assign them prototypes directly, without using constructor functions. But as you used new, which means you're using constructor functions, I won't go into detail on that.
Now, you don't have to use the prototype features of JavaScript if you don't want to. You can, for instance, do this:
function Init(name) {
var name = name;
this.displayName = function() {
alert(name);
};
}
var i = new Init("Mozilla");
i.displayName();
That doesn't use the prototype features of JavaScript, instead it just creates a new displayName function every time you call Init and assigns it directly to the object. (Any reasonable quality JavaScript engine will be smart enough to reuse the code of the function, but there will be distinct function objects for each instance). The above also makes the name property completely private, because the function we create on each call is a closure over the local variable name. (More: Closures are not complicated)
To create something like a member function you need to add it to the protoype of the constructor function:
function init() {
this.name = 'Mozilla';
}
init.prototype.displayName = function() {
alert(this.name);
}
I also highly recommend you to read something about how the object system in JavaScript works. There's a pretty good article about it on MDN: https://developer.mozilla.org/en-US/docs/JavaScript/Introduction_to_Object-Oriented_JavaScript
The following should work:
function Init() {
var name = "Mozilla";
this.displayName = function() {
alert(name);
}
}
a = new Init();
a.displayName()
One of the standards you can use is
var init = (function() {
var name = "Mozilla"; // Shared by all instances
function init() {
this.name = "IE"; // Spesific to the created instance
}
init.prototype = {
displayName: function() {
alert(name);
alert(this.name);
}
}
return init;
})();
var a = new init();
a.displayName();
In your first method:
function init() {
var name = "Mozilla";
function displayName() {
alert(name);
} } a = new init(); a.displayName()
function displayName(){} only can be called in init(), it's like private function, so can not be used as a public function of the object(init())
I have a Javascript Object structured after the Module Pattern. I have several private function in it which are called from other sibling "private" functions. How can I access another variable/function without the potential to accidentally access a global/external variable/object/function?
function doSomething() {
alert("Something I don't want to do");
}
var My.Namespaced.SingletonClass = (function() {
var init = function() {
doSomething();
}
var doSomething = function() {
alert("Something I want to do");
}
return {
"init": init;
}
})();
My.Namespaced.SingletonClass.init();
My guess is that the above code would in fact access the correct, inner doSomething function, but I'd like some more security than that. How can I explicitly address the inner/nested function without fear of accidentally calling functions or addressing objects in the scope around my singleton?
Short version: you can't. If doSomething isn't defined as a sibling of init, then JavaScript will search successively broader scopes until it finds a doSomething function, or it runs out of scopes to search.
Longer version: you can prevent this sort of behavior by using a private object to hold your private helper functions, like this:
function doSomething() {
alert("Something I don't want to do");
}
// Assuming My.Namespaced is already defined:
My.Namespaced.SingletonClass = (function() {
var helpers = {};
helpers.doSomething = function() {
alert("Something I want to do");
}
var init = function() {
helpers.doSomething();
}
return {
init: init
}
})();
My.Namespaced.SingletonClass.init();
I'm not sure if it's important that the helper functions are truly siblings (but I don't see why that would particularly matter).
Also keep in mind that My and My.Namespaced need to be defined before you tack on SingletonClass - and there's no need to use JSON-style quoting for keys in the object you're returning.