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.
Related
If a constructor and it's prototype are defined in the same module, say AMD module, is it acceptable to make class private fields global for the module to be accessible within prototype instead of defining them with underscore inside a constructor?
So is this better:
define(function (require) {
"use strict";
var steps = 0;
function Constructor(_steps) {
steps = _steps;
}
Constructor.prototype.go = function () {
steps += 1;
};
then this:
define(function (require) {
"use strict";
function Constructor(_steps) {
this._steps = _steps;
}
Constructor.prototype.go = function () {
this._steps += 1;
};
?
TL;DR: doesn't really matter (it's just a minor implementation detail)
Two different solutions. One isn't necessarily "better" than the other, they just have different use cases.
If you're using the constructor/prototype pattern, then it makes sense in an object-oriented sense to set the constructor parameters on the instance itself (using this.<whatever-prop>). When you instead decide to use the constructor only for the sake of its side effects (by setting someModuleVariable based on the parameter passed to the constructor), it can unnecessarily obfuscate the code.
Having a "private" variable that's accessible to the entire module, however, is an extremely common pattern... For example, when using singleton objects, because scoped variables are never destroyed when you leave the execution context of the function, the module can still query that "module-local" variable.
The only thing that rubs me the wrong way is using the constructor only for the sake of its side effects... why would I use a constructor then, when one of the main purposes of a constructor is the implicitly set properties on the instance?
To separate these two ideas, a common pattern is to use an init method inside of the prototype, because that's a good place to harbor all of your desired side effects. For example, one could suggest doing this:
var Module = (function() {
var somethingPrivate;
function SomeObject(someProp) {
// rely on the constructor to set instance properties
this.someProp = someProp;
}
SomeObject.prototype = {
init: function(_somethingPrivate) {
// all of your side effects in here, such as:
somethingPrivate = _somethingPrivate;
}
};
return SomeObject;
}());
var module = new Module('Hello world! I belong to the instance');
module.init('I am a module-specific variable!');
Of course, however, this isn't saying that there aren't circumstances where you might want to rely on a constructor for its side effects. But in the example you gave, it doesn't even look like a constructor is necessary (even though I understand the example is contrived just for the sake of demonstrating the problem).
Where and how you use _ underscores are mostly irrelevant, just as a side note. They're good in some cases, like to differentiate pseudo-private properties from "public" properties, but I think that's more of a convention than a pattern that's been set in stone.
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";
};
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.
Just saw some interesting code while doing a typo in coffee-script. I got the following code
var Mamal, mam;
Mamal = (function() {
var __priv_func;
function Mamal() {}
Mamal.prototype.simple_var = 5;
Mamal.prototype.test = function() {
return __priv_func(this);
};
__priv_func = function(instance) {
return alert(instance.simple_var);
};
return Mamal;
})();
mam = new Mamal();
mam.simple_var = 10;
mam.test();
Now I've read alot about the module pattern in javascript and why its a bad thing (takes more memory, longer to create...) but of course the upside is having truly private functions/variables. Wouldn't the above code be a good way to create private functions (this wouldn't work for variables, unless you wanted static private variables) as the function is only created once in the closure?
One of the upsides of the module pattern is also the execution speed of functions as the code doesn't have to look up the prototype chain. Would this theoretically give the same speed improvements?
To highlight the points I was making, because clearly there was more to the question than just the title:
Yes a module pattern is a good and commonly used way to create private (er, local) data (functions or whatever), and export some sort of interface. Since a function is the only way to create variable scope, it's the only way to create private functions.
Because the functions will be shared by all objects created from Mamal, they're not useful for a functional inheritance pattern (references to functional inheritance have been removed from the question).
There's no performance improvement over lookups in the prototype chain, because the prototype chain needs to be traversed anyway just to get to your private functions.
To address specific questions points in the updated post:
"Would this be a good way to do private functions?"
Sure, but that's because having a function nested in another is the only way to scope a function.
"Now I've read alot about the module pattern in javascript and why its a bad thing..."
For a one-time use module, I don't see any issue. Also, any data referenced by variables that are no longer needed after the module function exits is free for garbage collection. This wouldn't be the case if they were global, unless you nullified them.
"...of course the upside is having truly private functions/variables..."
Yes, though some would take exception to the use of the word "private". Probably "local" is a better word.
"...this wouldn't work for variables, unless you wanted static private variables..."
Yes, though again some may take exception to the use of the word "static".
"Wouldn't the above code be a good way to create private functions...as the function is only created once in the closure?"
Yes again, nested functions are the only way to make them "private" or rather local.
But yes, as long as the function only ever needs to access the public properties of the objects (which are accessible to any code that can access the object) and not local variables of the constructor, then you should only create those functions once, whether or not you use a module pattern.
"One of the upsides of the module pattern is also the execution speed of functions as the code doesn't have to look up the prototype chain. Would this theoretically give the same speed improvements?"
No, you haven't exported your private functions directly, but rather the only way to call them is by traversing the prototype chain.
But if you ditched the prototype chain, and added functions as properties directly on the objects created, then you'd have some improvement there.
Here's an example:
Mamal = (function() {
var __priv_func;
function Mamal() {
this.test = __priv_func;
}
Mamal.prototype.simple_var = 5;
__priv_func = function() {
return alert( this.simple_var );
};
return Mamal;
})();
Now you've eliminated the prototype chain in the lookup of the test function, and also the wrapped function call, and you're still reusing the __priv_func.
The only thing left that is prototyped is the simple_var, and you could bring that directly onto the object too, but that'll happen anyway when you try to modify its value, so you might as well leave it there.
Original answer:
If you're talking about a module pattern, where you set up a bunch of code in (typically) an IIFE, then export methods that have access to the variables in the anonymous function, then yes, it's a good approach, and is pretty common.
var MyNamespace = (function () {
// do a bunch of stuff to set up functionality
// without pollution global namespace
var _exports = {};
_exports.aFunction = function() { ... };
_exports.anotherFunction = function() { ... };
return _exports;
})();
MyNamespace.aFunction();
But in your example, I don't see and advantage over a typical constructor, unless you decide to use the module pattern as above.
The way it stands right now, the identical functionality can be accomplished like this without any more global pollution, and without the wrapped function:
var Mamal, mam;
Mamal = function() {};
Mamal.prototype.test = function() {
return console.log(this.simple_var);
};
Mamal.prototype.simple_var = 5;
mam = new Mamal();
mam.simple_var = 10;
mam.test();
" Wouldn't the above code be a good way to create private functions (this wouldn't work for variables, unless you wanted static private variables) as the function is only created once in the closure?"
Given the rewritten code above, the function is still only created once. The prototype object is shared between objects created from the constructor, so it too is only created once.
"One of the upsides of functional inheritance is also the execution speed of functions as the code doesn't have to look up the prototype chain. Would this theoretically give the same speed improvements?"
In your code, the function is called via a function in the prototype chain, so it has that same overhead, plus the overhead of finding the local function in the variable scope and invoking that function as well.
So two lookups and two function invocation instead of one lookup and one invocation.
var Mamal, mam1, mam2;
Mamal = (function() {
//private static method
var __priv_func = function() {
return 1;
};
function Mamal() {
}
Mamal.prototype.get = function() {
return __priv_func();
};
Mamal.prototype.set = function(i) {
__priv_func = function(){
return i;
};
};
return Mamal;
})();
mam1 = new Mamal();
mam2 = new Mamal();
console.log(mam1.get()); //output 1
mam2.set(2);
console.log(mam1.get()); //output 2
The function __priv_func is not only private, but also static. I think it's a good way to get private function if 'static' does not matter.
Below is a way to get private but not static method. It may take more memory, longer to create.......
var Mamal, mam1, mam2;
function Mamal() {
//private attributes
var __priv_func = function() {
return 1;
};
//privileged methods
this.get = function() {
return __priv_func();
};
this.set = function(i) {
__priv_func = function(){
return i;
};
};
}
mam1 = new Mamal();
mam2 = new Mamal();
console.log(mam1.get()); // output 1
console.log(mam2.get()); // output 1
mam2.set(2);
console.log(mam1.get()); // output 1
console.log(mam2.get()); // output 2