I'm trying to learn the JavaScript module pattern referenced here. Everything looks great but I keep seeing different ways to create the module.
In the article referenced above he access the module's public methods by using YAHOO.myProject.myModule.init(); without calling new. But then I've seen a few people do something like var module = new YAHOO.myProject.myModule();. Should new be used and why?
There is no right or wrong answer to this.
Sometimes a module will contain an object, where no new keyword is needed.
define( [], function() {
return {
foo: "bar"
};
};
Sometimes a module will contain a constructor for an object, where a new keyword is needed.
define( [], function() {
return function() {
this.foo = "bar";
};
};
Sometimes a module will contain a function that returns new objects, where no new keyword is needed.
define( [], function() {
var SomeConstructor = function() {
this.foo = "bar";
};
return function() {
return new SomeConstructor();
};
};
Usage depends partially on what you are trying to accomplish and partially on your teams coding preference.
That all comes down to exactly what is inside of myModule.
If the intent of myModule is to return a 100% new object, and inside of myModule there are a whole lot of assignments using this.<X> = <Y>, then yes, new would be the anticipated course of action.
...if it wasn't looking to create a new object, then this would refer to myProject and any this.<X> = <Y>; assignments would be reflected as YAHOO.myProject.<X> = <Y>; and using new would be a bad idea, if you were expecting then to use YAHOO.myProject.<X> to do something...
So it really all depends on what's going on.
A lot of JavaScript-fluent programmers (those who are used to thinking about JS differently than writing C++ or Java or C#) will try to avoid using patterns where new is required in cases like these, because it's ambiguous as to what myModule is and there are a lot of other suitable patterns which are dead-simple to implement in JS.
As modules usually are singletons and not constructors, you should not use new. See also this answer.
The new keyword in Javascript allocates a new object, and then sets it as this in the constructor invocation. If you're simply using a module as a function that will return an object allocated in the function itself, new is not necessary.
Because, when declaring at least, javascript makes no distinction between objects and functions, new has to be used when you create the object. However, you'll often fine that patterns like this occur.
function myObject() {
if (!(this instanceof myObject)) {
return new myObject();
}
}
This is done to make sure that it's always an instance of myObject.
Related
I was just looking into ways of defining singletons in JavaScript, and after looking into a few samples I thought about the following way which I haven't found anywhere:
function MyClass() {
if (MyClass._sharedInstance === undefined) {
// actual constructor code
MyClass._sharedInstance = this;
}
return MyClass._sharedInstance;
}
MyClass._sharedInstance = undefined;
Seems to work fine... but the fact that I couldn't find this anywhere makes me suspicious. Is there any reason not to do a singleton that way, especially considering the many little pitfalls of JavaScript. I know that by simply doing a var MyClass = { /* MyClass Stuff */ } I can achieve a singleton with less code, but for the sake of consistency I would like to define all my classes using prototypes.
The proposed solution does not seem to "solve" anything1; as such,
I recommend a standard variation of a "simple module pattern" using an idiomatic IIFE:
MySingleton = (function () {
// This function is only executed once
// and whatever is returned is the singleton.
return {
// Expose members here
};
})();
Depending on specific need a new'ed object could also be returned, making this pattern flexible without the need to introduce a separate "singleton" field and guard, e.g.
MySingleton = (function () {
// Contrived, but valid - any object returned
// functions as the singleton.
function MyClass {}
return new MyClass();
})();
1If anything, it may lead to some "WTF?" moments when new MyClass() returns a shared/singleton object which is not "normal" behavior.
I have a question for you
As I know, new operator works this way
function fakeNew(Ctor) {
var instance = Object.create(Ctor.prototype);
instance.constructor();
// I skip the conditional for simplicity
return instance;
}
It all begin when I did a Object.create polifill so I could create objects without using new.
Object.create = function(proto) {
function F() { }
F.prototype = proto;
return new F();
}
I started creating a lot of objcts and prototiping them, but as many times then need to initializa its properties I did a .init() method to them
var base = {
init: function() {
EmitterMixin.call(this);
return this;
}
};
var obj = Object.create(base).init();
But of course, I had to rembember to return this always from .init() and many times I forget it or worst, I forgot to call .init(). So trying to simplify object initialization I wanted to create a global helper to do it: invoke Object.create, invoke the initializer function and return this.
function create(proto) {
var child = Object.create(proto);
child.init();
return child;
}
Then was when I wanted to hit my head against the wall when I realized what I was doing was virtually what new operator does but a lot slower. And in case the polifill applies I would even use new under the hood.
So I ask myself, what benefits throwing new? It's notably quicker on main browsers and because of javascript nature we usually need to call a initualizer function, something than new does from it's begining.
And worst, I've noticed than I used two different types of objects, "abstract" and "instances", the bigger difference is than for instances I had to invoke .init() while with abstracts it was not necesasary because they will only be used to be prototypes of other objects. And I've already seen this pattern while using new:
function Foo() { }
Foo.prototype.method = function() { ... };
function Bar() { }
// "abstract" doesnt invoke initializer
Bar.prototype = Object.create(Foo.prototype);
Bar.prototype.other = function() { ... };
// "instance", the constructor is called as initializer
var obj = new Bar();
Is there really a benefit if we stop seeing new? are we sure it's not a higher-level tool than simplifies something we'll have to do anyway?
What pros/cons do you see about new and Object.create?
I have tried both approaches and I don't personally see any problem with the traditional approach using new. The main argument for Object.create is that it makes the prototypal inheritance more clear - you don't have to understand the intricacy of the prototype property on function constructors and how that relates to the actual prototype of the object. But it does require that initialization be a separate step.
My preferred approach is to combine the two approaches, e.g.:
function Animal(name) {
this.name = name || null;
}
Animal.prototype.eat = function() {
console.log('yum');
}
function Cat(name) {
Animal.call(this, name);
}
Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.constructor = Cat;
Cat.prototype.meow = function() {
console.log('meow');
}
var garfield = new Cat('garfield');
garfield.eat();
garfield.meow();
Object.create is better for inheritance here than Cat.prototype = new Animal() for two reasons:
If you wanted to require the name parameter (throwing an exception if it wasn't passed), you could do so and the inheritance (Cat.prototype = Object.create(Animal.prototype)) would still work.
If you forgot to call the Cat constructor from the Animal constructor, all of the properties that would have been created by the Animal constructor will be undefined instead, allowing you to quickly realize the mistake.
Although this approach (using constructor functions and new) is less "purely" prototypal, it's still prototypal inheritance and as long as you understand how to use it correctly it works just fine, and requires a little less typing than the Object.create approach.
I wrote some other notes about this in the documentation for my Javascript OO library, simpleoo. (Note: I may be changing the API soon for that library; I'm linking to it mainly because the documentation discusses some of these concepts in more detail.)
The problem with functional inheritance is that if you want to create many instances then it will be slow because the functions have to be declared every time.
The problem with prototypal inheritance is that there is no way to truly have private variables.
Is it possible to mix these two together and get the best of both worlds? Here is my attempt using both prototypes and the singleton pattern combined:
var Animal = (function () {
var secret = "My Secret";
var _Animal = function (type) {
this.type = type;
}
_Animal.prototype = {
some_property: 123,
getSecret: function () {
return secret;
}
};
return _Animal;
}());
var cat = new Animal("cat");
cat.some_property; // 123
cat.type; // "cat"
cat.getSecret(); // "My Secret"
Is there any drawbacks of using this pattern? Security? Efficiency? Is there a similar pattern out there that already exists?
Your pattern is totally fine.
There are a few things that you'd want to keep in mind, here.
Primarily, the functions and variables which are created in the outermost closure will behave like private static methods/members in other languages (except in how they're actually called, syntactically).
If you use the prototype paradigm, creating private-static methods/members is impossible, of course.
You could further create public-static members/methods by appending them to your inner constructor, before returning it to the outer scope:
var Class = (function () {
var private_static = function () {},
public_static = function () {},
Class = function () {
var private_method = function () { private_static(); };
this.method = function () { private_method(); };
};
Class.static = public_static;
return Class;
}());
Class.static(); // calls `public_static`
var instance = new Class();
instance.method();
// calls instance's `private_method()`, which in turn calls the shared `private_static();`
Keep in mind that if you're intending to use "static" functions this way, that they have absolutely no access to the internal state of an instance, and as such, if you do use them, you'll need to pass them anything they require, and you'll have to collect the return statement (or modify object properties/array elements from inside).
Also, from inside of any instance, given the code above, public_static and Class.static(); are both totally valid ways of calling the public function, because it's not actually a static, but simply a function within a closure, which also happens to have been added as a property of another object which is also within the instance's scope-chain.
As an added bonus:
Even if malicious code DID start attacking your public static methods (Class.static) in hopes of hijacking your internals, any changes to the Class.static property would not affect the enclosed public_static function, so by calling the internal version, your instances would still be hack-safe as far as keeping people out of the private stuff...
If another module was depending on an instance, and that instance's public methods had been tampered with, and the other module just trusted everything it was given... ...well, shame on that module's creator -- but at least your stuff is secure.
Hooray for replicating the functionality of other languages, using little more than closure.
Is it possible to mix functional and prototypical inheritance together and get the best of both worlds?
Yes. And you should do it. Instead of initializing that as {}, you'd use Object.create to inherit from some proto object where all the non-priviliged methods are placed. However, inheriting from such a "class" won't be simple, and you soon end up with code that looks more like the pseudo-classical approach - even if using a factory.
My attempt using both prototypes and the singleton pattern combined. Is there a similar pattern out there that already exists?
OK, but that's something different from the above? Actually, this is known as the "Revealing Prototype Pattern", a combination of the Module Pattern and the Prototype Pattern.
Any drawbacks of using this pattern?
No, it's fine. Only for your example it is a bit unnecessary, and since your secret is kind of a static variable it doesn't make much sense to me accessing it from an instance method. Shorter:
function Animal(type) {
this.type = type;
}
Animal.prototype.some_property = 123;
Animal.getSecret = function() {
return "My Secret";
};
So there's this so-called module pattern for creating singletons with private members:
var foo = (function () {
var _foo = 'private!';
return {
foo: function () { console.log(_foo); },
bar: 'public!'
}
})();
There's also this method that I found on my own, but haven't seen anything written about:
var foo = new function () {
var _foo = 'private!';
this.bar = 'public!';
this.foo = function () { console.log(_foo); };
}
I'm thinking there must be a reason why nobody writes about this while there's tons of articles about the module pattern. Is there any downside to this pattern? Speed, or browser compatibility perhaps?
In this case it seems you are using only one instance object of that "class". So may want to take look at what Douglas Crockford thinks about putting new directly in front of function:
By using new to invoke the function, the object holds onto a worthless prototype object. That wastes memory with no offsetting advantage. If we do not use the new, we don’t keep the wasted prototype object in the chain. So instead we will invoke the factory function the right way, using ().
So according to the renown javascript architect of Yahoo! you should use the first method, and you have his reasons there.
More-or-less, they give you the same result. It's just a matter of which path you want to take for it.
The 1st may be more popular since it's simply the mixture of 2 already common patterns:
(function closure() {
var foo = 'private';
/* ... */
}())
var singleton = {
bar : 'public'
};
However, prototype chaining would be the benefit of the 2nd pattern since it has its own constructor.
var singleton = new function Singleton() { };
assert(singleton.constructor !== Object);
singleton.constructor.prototype.foo = 'bar';
assert(singleton.foo === 'bar');
I don't see any substantial difference between the two. I would prefer the latter simply since it has much less punctuation clutter.
On the other hand the "module pattern" approach seems to be the most common and is becoming a well known pattern (due to the rise in JQuery). It might be better to stick with this recognised pattern not because it has any more technical merit than the other approach but just because it will likely be more recognizable (despite the heavy punctuation).
Douglas Crockford writes about the second one. As Greg says in his comments, I thought it was quite common, and I've used it in the past.
Edit: to actually answer your question - there's no downsides, the two are functionally equivalent (both create a closure containing the "private variables" and exposing other variables/methods publically), and have exactly the same browser support and performance characteristics. It just comes down to a matter of syntax - basically, where you put the () to actually invoke this function and get your closure, and whether you use the new keyword.
Just finished reading Crockford's "JavaScript: The Good Parts" and I have a question concerning his stance on the psuedo-classical vs. prototypal approaches. Actually I'm not really interested in his stance; I just want to understand his argument so I can establish a stance of my own.
In the book, Crockford seems to infer that constructor functions and "all that jazz" shouldn't be used in JavaScript, he mentions how the 'new' keyword is badly implemented - i.e. non-Constructor functions can be called with the 'new' keyword and vice versa (potentially causing problems).
I thought I understood where he was coming from but I guess I don't.
When I need to create a new module I would normally start of like this:
function MyModule(something) {
this.something = something || {};
}
And then I would add some methods to its prototype:
MyModule.prototype = {
setSomething : function(){},
getSomething : function(){},
doSomething : function(){}
}
I like this model; it means I can create a new instance whenever I need one and it has its own properties and methods:
var foo = new MyModule({option1: 'bar'});
// Foo is an object; I can do anything to it; all methods of the "class"
// are available to this instance.
My question is: How do I achieve the above using an approach more suited to JavaScript? In other words, if "JavaScript" were a person, what would she suggest?
Also: What does Crockford mean when he says a particular design pattern "is more expressive" then another?
See: Is JavaScript's “new” Keyword Considered Harmful?
It's important to remember that Crockford, like so many other JavaScript programmers, first approached the language with an eye toward "fixing" it - making it more like other (so-called "classical") OO languages. So a large amount of structural code was written, libraries and frameworks built, and... then they started to realize that it wasn't really necessary; if you approach JS on its own terms, you can get along just fine.
The prototypal variant for the example you have looks like the following in my understanding:
Object.beget = function (o) { /* Crockfords replacement for the new */ }
var myModule = {
something : null,
getSomething : function () {},
setSomething : function () {},
doSomething : function () {}
};
And then you can do:
var foo = Object.beget(myModule);
foo.something = bar;
UPDATE: You can also use the builder pattern to replace a constructor like this:
var myModuleBuilder = {
buildMyModule : function (something) {
var m = Object.beget(myModule);
m.something = something || {};
return m;
}
}
so then you can do:
var foo = myModuleBuilder.buildMyModule(something);
Your implementation is problematic because you're replacing the entire prototype object, losing the properties of the inherited function prototype and it would also break, or at least make it more difficult, the ability to make use of inheritance later on if you wrote other classes the same way.
A method more suited to Javascript would be:
var MyClass = function (storeThis) {
this.storage = storeThis
}
MyClass.prototype.getStorage = function (){
return this.storage;
}
MyClass.prototype.setStorage = function (newStorage){
this.storage = newStorage;
}
Use it:
var myInstance = new MyClass("sup");
alert("myInstance storage: " + myInstance.getStorage());
myInstance.setStroage("something else");
As for the 'new' keyword and Crawford's problems with it, I can't really answer, because I haven't read the book, but I can see how you could create a new object by calling any function with the new keyword, including functions that are supposed to be methods of a class.
And when someone says something, such as a design pattern, is more 'expressive', he or she generally means that the design pattern is clear and simple to understand as to what it is achieving and how.
Javascript isn't a person so she can't really suggest what you do.
None of the answers above have mentioned the plain-old functional style of inheritance, which I tend to find is the simplest.
function myModuleMaker(someProperty){
var module = {}; //define your new instance manually
module.property = someProperty; //set your properties
module.methodOne = function(someExternalArgument){
//do stuff to module.property, which you can, since you have closure scope access
return module;
}
}
Now to make a new instance:
var newModule = myModuleMaker(someProperty);
You still get all the benefits of pseudoclassical this way, but you suffer the one drawback that you're making a new copy of all your instance's methods every time you instantiate. This is probably only going to matter when you start having many hundreds (or indeed, thousands) of instances, which is a problem most people seldom run into. You're better off with pseudoclassical if you're creating truly enormous data structures or doing hard-core animations with many, many instances of something.
I think it's hard to argue that either method is "bad practice" per se.