Object litterals vs Module pattern - javascript

I would like to understand clearly the difference between those two following patterns. In fact, the second one allows to mimic public and private method, but is there any other difference ?
var myModule = {
myProperty: "someValue",
...
myMethod: function () {
console.log( "Anything" );
}
};
myModule.myMethod();
and this :
var myModule = (function(){
var myProperty= "someValue";
...
return {
myMethod: function(){
console.log('something');
}
}
})();
myModule.myMethod();

The second one is essentially just like the first, except that it also provides for a closure around the object where "private" variables can be kept.
Specifically, if you set up an example like the second such that it had no local variables and no parameters to the anonymous function, it'd be exactly like not having the anonymous function at all.

Related

Passing arguments to a Javascript IIFE constructor

I'm trying to get my head around Javascript OO, using the IIFE module pattern to mimic a class:
var MyClass = (function() {
// Constructor
return function() {
return {
foo: 'foo'
}
}
}());
I'm passing arguments with something like:
var MyClass = (function() {
// Constructor
return function(arg) {
return {
foo: function() {
return 'foo'+arg
}
}
}
}());
To mimic classical inheritance I am using the pattern suggested here:
function inherit(base, child, obj) {
child.prototype = Object.create(base.prototype);
child.prototype.constructor = child;
obj&&Object.keys(obj).forEach(function(key){
child.prototype[key] = obj[key];
})
}
var Base = (function() {
var init = function() {};
init.prototype = {
foo: function() {
return "foo";
}
};
return init;
}());
var Child = (function() {
var init = function() {
Base.call(this);
};
inherit(Base, init, {
bar: function() {
return 'bar';
}
});
return init;
}());
So far so good. My only problem is in understanding how to pass parameters to my class constructor when I'm doing inheritance in the above way. I like the fact that in the 'pure' IIFE module I can simply refer to the constructor parameter in any functions defined within it, so that they become closures. But how do I access constructor params when I'm adding these subsequent functions using the constructor variable, as in the inheritance example above? I suppose I could do something like:
var init = function(arg) {
this.theArg = arg;
};
Then I can access it within anything subsequent:
init.prototype = {
foo: function() {
return "foo"+this.theArg;
}
};
And for the child:
var init = function(arg) {
Base.call(this, arg);
};
This makes arg available to the outside world, so to make it read-only I suppose a getter would work:
var init = function(arg) {
var theArg = arg;
this.getArg = function() { return theArg };
};
On the face of it I can't see anything wrong with that, and I can't think of a better alternative. Is there one? Am I missing something obvious?
I can't think of a better alternative. Is there one?
No. Not in your example.
I like the fact that in the 'pure' IIFE module I can simply refer to the constructor parameter in any functions defined within it, so that they become closures.
You can access args in each function because, in your first example, you are defining foo on each object instance separately. Therefore each definition of foo has a separate closure containing the args passed when it was defined.
This is also only possible, because foo is defined within the scope containing your args.
But how do I access constructor params when I'm adding these subsequent functions ... in the inheritance example above?
By using the classical inheritance patten you found, you are now defining the foo function on the constructor prototype. This means that only a single foo definition exists which is inherited by all instances created using your constructor. So foo can not be made specific to each instance anymore.
As you have figured, it also means foo is no longer defined inside the scope containing args and has no direct access.
You are therefore correct by assigning args to this.thisArgs which allows foo to access thisArgs on each instance. You have made foo a general case function that can handle any instance it is applied to.
Passing arguments to the IIFE constructor: The IIFE itself is not the constructor, it simply builds the constructor object. The IIFE's scope has long since been returned by the time the constructor itself is invoked.
Am I missing something obvious?
Yes. Javascript is a prototypical language. It was never meant to be like "classical" languages. Just let it be Javascript. :)

prototype on single instances of functions

If I know that I only will create one instance of the MyClass function below, which of my two snippets below would you prefer? Should I stick with the latter, even though I know that I'll only create one instance of the function?
I know that prototype is useful from a performance perspective when sharing methods across all instances of a function, but in this case I would like to hear your input.
var MyClass = (function () {
var cls = function () { };
cls.prototype = {
init: function(data){
}
};
return cls;
})();
vs
var MyClass = (function () {
var cls = function () {
this.init = function(data){
}
};
return cls;
})();
Your second code snippet is a syntax error, you're trying to put a property initializer where a statement is expected. (Not anymore)
If you're only going to have a single object that you need the init function on, then:
var MyObject = {
init: function(data) {
// ...
}
};
Then you don't even need to call a function to create it, it's already there.
If you want to have truly private variables and such (which I assume is the reason for your outer anonymous functions), then:
var MyObject = (function() {
var trulyPrivateDataHere;
return {
init: function(data) {
// ...
}
};
})();
I prefer this because it's clear and direct: You're creating the actual object. I don't see any need for a constructor function if you're only ever going to create a single instance.
But if it has to be a constructor function, I guess I'd very marginally prefer your second option, because it's simpler, and simple is good barring the need for complexity.

Javascript namespacing - is this particular method good practice?

I'm a javascript newbie, and I've come up with the following scheme for namespacing:
(function() {
var ns = Company.namespace("Company.Site.Module");
ns.MyClass = function() { .... };
ns.MyClass.prototype.coolFunction = function() { ... };
})();
Company.namespace is a function registered by a script which simply creates the chain of objects up to Module.
Outside, in non-global scope:
var my = new Company.Site.Module.MyClass();
I'm particularly asking about the method by which I hide the variable ns from global scope - by a wrapping anonymous function executed immediately. I could just write Company.Site.Module everywhere, but it's not DRY and a little messy compared to storing the ns in a local variable.
What say you? What pitfalls are there with this approach? Is there some other method that is considered more standard?
You dont need to scope classes like that, its only necessary if you have global variables outside of the class. I use this approach...
MyApp.MyClass = function() {
};
MyApp.MyClass.prototype = {
foo: function() {
}
};
Also note that I use a object literal for a cleaner prototype declaration
However if you need to scope global variables then you can do
(function() {
var scopedGlobalVariable = "some value";
MyApp.MyClass = function() {
};
MyApp.MyClass.prototype = function() {
foo: function() {
}
};
})();
Your approach looks fine to me.
However, you can also do this slightly different, by returning the "class" from the self-executing function:
Company.Site.Module.MyClass = (function() {
var MyClass = function() { ... };
MyClass.prototype.foo = function() { ... };
return MyClass;
})();
This strips at least all the ns. prefixes. The namespace function can still be utilized to create the objects, but outside of the self-executing function.

Difference between two JavaScript object types

I see objects in JavaScript organized most commonly in the below two fashions. Could someone please explain the difference and the benefits between the two? Are there cases where one is more appropriate to the other?
Really appreciate any clarification. Thanks a lot!
First:
var SomeObject;
SomeObject = (function() {
function SomeObject() {}
SomeObject.prototype.doSomething: function() {
},
SomeObject.prototype.doSomethingElse: function() {
}
})();
Second:
SomeObject = function() {
SomeObject.prototype.doSomething: function() {
},
SomeObject.prototype.doSomethingElse: function() {
}
}
Both of those examples are incorrect. I think you meant:
First:
var SomeObject;
SomeObject = (function() {
function SomeObject() {
}
SomeObject.prototype.doSomething = function() {
};
SomeObject.prototype.doSomethingElse = function() {
};
return SomeObject;
})();
(Note the return at the end of the anonymous function, the use of = rather than :, and the semicolons to complete the function assignments.)
Or possibly you meant:
function SomeObject() {
}
SomeObject.prototype.doSomething = function() {
};
SomeObject.prototype.doSomethingElse = function() {
};
(No anonymous enclosing function.)
Second:
function SomeObject() {
}
SomeObject.prototype = {
doSomething: function() {
},
doSomethingElse: function() {
}
};
(Note that the assignment to the prototype is outside the SomeObject function; here, we use : because we're inside an object initializer. And again we have the ; at the end to complete the assignment statement.)
If I'm correct, there's very little difference between them. Both of them create a SomeObject constructor function and add anonymous functions to its prototype. The second version replaces the SomeObject constructor function's prototype with a completely new object (which I do not recommend), where the first one just augments the prototype that the SomeObject constructor function already has.
A more useful form is this:
var SomeObject;
SomeObject = (function() {
function SomeObject() {
}
SomeObject.prototype.doSomething = doSomething;
function doSomething() {
}
SomeObject.prototype.doSomethingElse = doSomethingElse;
function doSomethingElse()
}
return SomeObject;
})();
There, the functions we assign to doSomething and doSomethingElse have names, which is useful when you're walking through code in a debugger (they're shown in call stacks, lists of breakpoints, etc.). The anonymous function wrapping everything is there so that the doSomething and doSomethingElse names don't pollute the enclosing namespace. More: Anonymouses anonymous
Some of us take it further:
var SomeObject;
SomeObject = (function() {
var p = SomeObject.prototype;
function SomeObject() {
}
p.doSomething = SomeObject$doSomething;
function SomeObject$doSomething() {
}
p.doSomethingElse = SomeObject$doSomethingElse;
function SomeObject$doSomethingElse()
}
return SomeObject;
})();
...so that not only do we see doSomething, but SomeObject$doSomething in the lists. Sometimes that can get in the way, though, it's a style choice. (Also note I used the anonymous function to enclose an alias for SomeObject.prototype, to make for less typing.)
First off, both snippets will not parse for me (Chrome) - you should use = in place of :. That said, my humble opinion follows.
The latter snippet is slightly strange, because you actually define methods on SomeObject's prototype at the time of the object construction, rather than at the parse time. Thus, if you have re-defined some method on SomeObject.prototype, it will get reverted to the original version once a new object is constructed. This may result in unexpected behavior for existing objects of this type.
The former one looks fine, except that the (function { ...} ())() wrapper may not be necessary. You can declare just:
function SomeObject() {}
SomeObject.prototype.doSomething = function() {}
SomeObject.prototype.doSomethingElse = function() {}
The actual difference between first and second in your questions is just:
var o = (function () {})(); # call this (A)
and
var o = function () {}; # call this (B)
Unfortunately, neither of the examples that you gave are written correctly and, while I don't think either will actually give an error at parse-time, both will break in interesting ways when you try to do things with the result.
To give you an answer about the difference between (A) and (B), (A) is the immediate function application pattern. The JavaScript Patterns book has a good discussion, which I recommend.
The actual problems in your code have been explained by other people while I was writing this. In particular T.J. Crowder points out important things.

Writing a Javascript library that is code-completion and code-inspection friendly

I recently made my own Javascript library and I initially used the following pattern:
var myLibrary = (function () {
var someProp = "...";
function someFunc() {
...
}
function someFunc2() {
...
}
return {
func: someFunc,
fun2: someFunc2,
prop: someProp;
}
}());
The problem with this is that I can't really use code completion because the IDE doesn't know about the properties that the function literal is returning (I'm using IntelliJ IDEA 9 by the way).
I've looked at jQuery code and tried to do this:
(function(window, undefined) {
var myLibrary = (function () {
var someProp = "...";
function someFunc() {
...
}
function someFunc2() {
...
}
return {
func: someFunc,
fun2: someFunc2,
prop: someProp;
}
}());
window.myLibrary = myLibrary;
}(window));
I tried this, but now I have a different problem. The IDE doesn't really pick up on myLibrary either.
The way I'm solving the problem now is this way:
var myLibrary = {
func: function() { },
func2: function() { },
prop: ""
};
myLibrary = (function () {
var someProp = "...";
function someFunc() {
...
}
function someFunc2() {
...
}
return {
func: someFunc,
fun2: someFunc2,
prop: someProp;
}
}());
But that seems kinda clunky, and I can't exactly figure out how jQuery is doing it. Another question I have is how to handle functions with arbitrary numbers of parameters.
For example, jQuery.bind can take 2 or 3 parameters, and the IDE doesn't seem to complain. I tried to do the same thing with my library, where a function could take 0 arguments or 1 argument. However, the IDE complains and warns that the correct number of parameters aren't being sent in. How do I handle this?
EDIT
I'm starting to wonder if this is an Idea9 issue because jQuery has the same problem. I don't seem to have this problem in other projects though.
I'm using IDEA with yahoo module pattern and my autocomplete works. Google for yahoo module pattern.
http://www.yuiblog.com/blog/2007/06/12/module-pattern/
http://ajaxian.com/archives/a-javascript-module-pattern
TEST = function() {
var SOME_CONSTANT='asd';
function privateStuff(){
var a = 'asd';
return a;
}
return{
someArray:[],
someMethod: function(foo, bar){
var foo = *1
}
,
myProperty:'test'
}
}();
TEST.*2
with *1 and *2 i marked places where i tried auto complete.
in *1 i get SOME_CONSTANT and privateStuff method, and if i put this.(autocomplete) i get access to all the methods and properties inside of return {} block
when i try autocomplete on *2 i get all the methods and properties inside return {} block.
SOME_CONSTANT and privateStuff method are invisibile there, because they are "private".
For me that level of autocomplete is quite fine.
I think will be great if you read something about Douglas Crockford. He is THE architect in yahou YUI framework. And after that you can have a better idea to how build a great framework. And for the parameter there are 2 options. 1.- send via object example
{ option :{ var1 : "value" , var2:"value"}, var3 : "value" }
And the you can check if the option exist.
The second one not to great is check if the parameter is undefined.
function foo(var1,var2){
var var1_this = null;
if(var1 != undefined)
var1_this = var1;
}
and just a comment why build a new javascript framework? use Prototype, JQuery, Mootols, YUI. why reinventing the wheel?
This is in reply to the comments to mwilcox's post.
That example will actually work. Since myLibrary is defined without var, it is automatically put into the global namespace and accessible as such. Through the closure created by the self-executing function, the private variables and methods are still accessible in the myLibrary methods. You can easily try this out by putting it into Firebug or Rhino.
These days, I do not tend to hide my variables, i.e. I use the Pseudoclassical pattern or the Prototypal pattern and prefix my intended private methods with an _:
// Pseudoclassical pattern
function Hello() {}
Hello.prototype = {
method1: function() {},
method2: function() {},
_pseudeoPrivate: function() {}
};
/* Prototypal pattern. To create multiple instances of this object,
you need a helper function such as
function beget(o) {
var F = function() {};
F.prototype = o;
return new F;
}
var instance = beget(world);
*/
var world = {
method1: function() {},
method2: function() {}
};
To prevent my code from polluting the global namespace, I have a build process that wraps my modules in a closure and exports the public api to the namespace. This technique is also used by jQuery. You can see that in their source code (look at intro.js & outro.js) on Github.
This would allow you to use a pattern that allows your IDE (or ctags with vim) to see your api, whilst also preventing the pollution of the global namespace.
I write my libraries like this:
function MyLibrary() {
// code
}
MyLibrary.prototype.memberFunc = function() {
// code
}
MyLibrary.prototype.memberVar = 5;
new MyLibrary();
This way, in Geany (which uses CTAGS) MyLibrary is well recognized (for the most part, for example, memberVar is recognized as a function) and autocompletion seems to work. I don't know about IDEA9, but you could try it this way (I have a hunch it's a bit more evolved than CTAGS).
I recommend that you don't use private variables, but I understand you want them hidden from the intellisense. This is how I would do it:
(function(){
var privateVar = "shhhh!";
var privateMethod = function(){}
myLibray = {
prop:42,
foo: function(){
return privateMethod()
},
bar: function(){
return privateVar;
}
}
})();
This way you can have your private stuff in a closure and your library should be accessible.
[ edited. I clumsily did not include myLibrary in the anonymous function and it could not see the private vars. oops. ]
BTW, my reasons for private variables being bad: http://clubajax.org/javascript-private-variables-are-evil/

Categories

Resources