jQuery-style function that can be accessed like an object - javascript

I am creating an AJAX API for a web service and I want to be able to call jQuery-like accessors.
jQuery seems to be able to execute 'jQuery' as a function, but also use it to directly access the object that is the result of the function EG:
jQuery();
jQuery.each({});
This is the trick that I can't seem to pull off:
myAPI('foo'); //output: 'foo'
myAPI('foo').changeBar(); //output: 'foo' 1
myAPI.changeBar(); //Error: not a function
I have seen the answers to similar questions, which are helpful, but don't really answer my question.
#8734115 - Really interesting, but you can't access the methods that were set by f.prototype.
#2953314 - Uses Multiple operations to create object instead of a single function.
here is my code:
(function(window) {
var h = function(foo) {
// The h object is actually just the init constructor 'enhanced'
return new h.fn.init(foo);
};
/**
* Methods defined at protoype.
*/
h.fn = h.prototype = {
constructor: h,
init: function(foo) {
console.log(foo);
return this;
},
splice : function () {},
length : 0,
bar : 0,
changeBar : function() {
this.bar++;
return this.bar;
}
};
h.fn.init.prototype = h.fn;
//Publish
window.myAPI =h;
}( window));
I'm sure I'm missing something simple :(

What jQuery is doing there is using jQuery as both a function and as a pseudo-namespace. That is, you can call jQuery: var divs = jQuery("div"); and you can use properties on it, e.g.: jQuery.each(...);.
This is possible because in JavaScript, functions are first-class objects, and so you can add arbitrary properties to them:
function foo() {
alert("Foo!");
}
foo.bar = function() {
alert("Bar!");
};
foo(); // "Foo!"
foo.bar(); // "Bar!"
That's literally all there is to it.
Within the call to bar, this will be the foo function (because this is determined entirely by how a function is called, not where it's defined). jQuery doesn't use this to refer to itself (usually it uses this to refer to DOM elements, sometimes to other things like array elements; when referring to itself, since it's a single thing, it just uses jQuery).
Now, you might want to ensure that your functions have proper names (whereas the function I assigned to bar above is anonymous — the property has a name, but the function does not). In that case, you might get into the module pattern:
var foo = (function() {
function foo() {
alert("Foo!");
}
function foo_bar() {
alert("Bar!");
}
foo.bar = foo_bar;
return foo;
})();
foo(); // "Foo!"
foo.bar(); // "Bar!"
That pattern also has the advantage that you can have private data and functions held within the scoping function (the big anonymous function that wraps everything else) that only your code can use.
var foo = (function() {
function foo() {
reallyPrivate("Foo!");
}
function foo_bar() {
reallyPrivate("Bar!");
}
function reallyPrivate(msg) {
alert(msg);
}
foo.bar = foo_bar;
return foo;
})();
foo(); // "Foo!"
foo.bar(); // "Bar!"
reallyPrivate("Hi"); // Error, `reallyPrivate` is undefined outside of the scoping function
In your code, you're assigning things to the prototype property of the function. That only comes into play when the function is called as a constructor function (e.g., via new). When you do that, the object created by new receives the function's prototype property as its underlying prototype. But that's a completely different thing, unrelated to what jQuery does where it's both a function and a pseudo-namespace.

You do not need any of that weirdness, to use stuff like $.each
you just attach functions to the function object instead
of the prototype object:
function Constructor() {
if (!(this instanceof Constructor)) {
return new Constructor();
}
}
Constructor.prototype = {
each: function() {
return "instance method";
}
};
Constructor.each = function() {
return "static method";
};
var a = Constructor();
a.each(); //"instance method"
Constructor.each(); //"static method"

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. :)

Creating inheritance on revealing modular pattern objects

I'm trying to create some kind of inheritance between objects:
var foo = (function(){
function doFooStuff(){
console.log(arguments.callee.name);
}
return {
doFooStuff: doFooStuff
}
})();
var bar = (function(){
$.extend(this, foo);
function doBarStuff(){
console.log(arguments.callee.name);
doFooStuff();
}
return {
doBarStuff: doBarStuff,
}
})();
bar.doBarStuff();
bar.doFooStuff(); //<-- Uncaught TypeError:
//Object #<Object> has no method 'doFooStuff'
http://jsfiddle.net/wRXTv/
Why isn't doFooStuff accessible here? Would you recommend another approach than using $.extend?
$.extend(this, foo);
this is not the object which you return from the function below (in fact it cannot be since it's created after this call), but the global object - check MDN's introduction to the this keyword.
For what you want to do, there are two ways:
Copy all properties from foo onto your bar object after it is created:
var bar = (function() {
…
return {…};
})();
$.extend(bar, foo);
You can do that as well directly on the returned object:
return $.extend({…}, foo);
A variant of this pattern allows you to overwrite foo properties. Copy foo into an empty object, then write your bar properties to it:
return $.extend({}, foo, {…});
Use prototypical inheritance. Create an object that inherits its properties from foo, and then write your bar properties to it:
return $.extend(Object.create(foo), {…});
Now when foo changes afterward, you still can access those new properties on bar (unless they're shadowed by own properties). Notice that Object.create might not be supported in legacy environments, but you can easily shim it.
As noted by #raina77ow, your doBarStuff function is flawed too. The doFooStuff function is not in the scope of your function, and you cannot change that. You never will be able to access the private declared functions and variables from the foo module, only those that are public - if you did need them, consider a different pattern or app design. However, doFooStuff is a property on the exported (public) foo object, from which bar inherits (regardless in which of the above demonstrated ways). Therefore, you can access it as a method of bar as well, usually by using this.doFooStuff().
You attempt to work with revealing module as if it were a constructor. Hence an attempt to extend this, wrong for many reasons. The most glaring, I suppose, is that neither the function is used as a constructor (no new) nor its context is changed. In plain words, this just points to a global object here.
But that's not the only problem. Consider that part of your code:
function doBarStuff(){
console.log(arguments.callee.name);
doFooStuff();
}
Here doFooStuff won't be in the scope even if you somehow manage to extend this. ) Remember, the scope resolution doesn't involve the context object.
So what's the solution? Well, I often use aggregation in similar cases:
var foo = (function(){
function doFooStuff(){
console.log(arguments.callee.name);
}
return {
doFooStuff: doFooStuff
}
})();
var bar = (function(){
var _super = foo;
function doBarStuff(){
console.log(arguments.callee.name);
_super.doFooStuff();
}
// static parent: further changes on `foo` won't affect `bar`,
// as $.extend takes the parent's current state
return $.extend({}, _super, {
doBarStuff: doBarStuff,
});
// dynamic parent: further changes on `foo` will affect `bar`,
// as extended object now has `foo` in its prototype chain
return $.extend(Object.create(_super), {
doBarStuff: doBarStuff,
});
})();
JS Fiddle.
Yes, it's aggregation, not inheritance. But so what? I'm still able to get the main prize - removing code duplication AND I'm able to control the usage of parent functions within the child module.
The problem with your code is that this in $.extend(this,foo) refers to the window object and not foo. Anonymous function are run in window's context.
I would recommend using a John Resig implementation of classical inheritance in javascript.
http://ejohn.org/blog/simple-javascript-inheritance/.
Extract:
var Person = Class.extend({
init: function(isDancing){
this.dancing = isDancing;
},
dance: function(){
return this.dancing;
}
});
var Ninja = Person.extend({
init: function(){
this._super( false );
},
dance: function(){
// Call the inherited version of dance()
return this._super();
},
swingSword: function(){
return true;
}
});
var p = new Person(true);
p.dance(); // => true
var n = new Ninja();
n.dance(); // => false
n.swingSword(); // => true
// Should all be true
p instanceof Person && p instanceof Class &&
n instanceof Ninja && n instanceof Person && n instanceof Class
It is because this is an anonymous function. This part of your function deceleration:
var foo = (function(){
function doFooStuff(){
console.log(arguments.callee.name);
}
return {
doFooStuff: doFooStuff
}
})();
Do you see that you are immediately invoking this function call and ultimately do not have access to doFooStuff within your return statement.
If you remove the anonymous function deceleration, it will work.

What is a best practice for ensuring "this" context in Javascript?

Here's a sample of a simple Javascript class with a public and private method (fiddle: http://jsfiddle.net/gY4mh/).
function Example() {
function privateFunction() {
// "this" is window when called.
console.log(this);
}
this.publicFunction = function() {
privateFunction();
}
}
ex = new Example;
ex.publicFunction();
Calling the private function from the public one results in "this" being the window object. How should I ensure my private methods are called with the class context and not window? Would this be undesirable?
Using closure. Basically any variable declared in function, remains available to functions inside that function :
var Example = (function() {
function Example() {
var self = this; // variable in function Example
function privateFunction() {
// The variable self is available to this function even after Example returns.
console.log(self);
}
self.publicFunction = function() {
privateFunction();
}
}
return Example;
})();
ex = new Example;
ex.publicFunction();
Another approach is to use "apply" to explicitly set what the methods "this" should be bound to.
function Test() {
this.name = 'test';
this.logName = function() {
console.log(this.name);
}
}
var foo = {name: 'foo'};
var test = new Test();
test.logName()
// => test
test.logName.apply(foo, null);
// => foo
Yet another approach is to use "call":
function Test() {
this.name = 'test';
this.logName = function() {
console.log(this.name);
}
}
var foo = {name: 'foo'};
var test = new Test();
test.logName()
// => test
test.logName.call(foo, null);
// => foo
both "apply" and "call" take the object that you want to bind "this" to as the first argument and an array of arguments to pass in to the method you are calling as the second arg.
It is worth understanding how the value of this in javascript is determined in addition to just having someone tell you a code fix. In javascript, this is determined the following ways:
If you call a function via an object property as in object.method(), then this will be set to the object inside the method.
If you call a function directly without any object reference such as function(), then this will be set to either the global object (window in a browser) or in strict mode, it will be set to undefined.
If you create a new object with the new operator, then the constructor function for that object will be called with the value of this set to the newly created object instance. You can think of this as the same as item 1 above, the object is created and then the constructor method on it is called.
If you call a function with .call() or .apply() as in function.call(xxx), then you can determine exactly what this is set to by what argument you pass to .call() or .apply(). You can read more about .call() here and .apply() here on MDN.
If you use function.bind(xxx) this creates a small stub function that makes sure your function is called with the desired value of this. Internally, this likely just uses .apply(), but it's a shortcut for when you want a single callback function that will have the right value of this when it's called (when you aren't the direct caller of the function).
In a callback function, the caller of the callback function is responsible for determining the desired value of this. For example, in an event handler callback function, the browser generally sets this to be the DOM object that is handling the event.
There's a nice summary of these various methods here on MDN.
So, in your case, you are making a normal function call when you call privateFunction(). So, as expected the value of this is set as in option 2 above.
If you want to explictly set it to the current value of this in your method, then you can do so like this:
var Example = (function() {
function Example() {
function privateFunction() {
// "this" is window when called.
console.log(this);
}
this.publicFunction = function() {
privateFunction.call(this);
}
}
return Example;
})();
ex = new Example;
ex.publicFunction();
Other methods such as using a closure and defined var that = this are best used for the case of callback functions when you are not the caller of the function and thus can't use 1-4. There is no reason to do it that way in your particular case. I would say that using .call() is a better practice. Then, your function can actually use this and can behave like a private method which appears to be the behavior you seek.
I guess most used way to get this done is by simply caching (storing) the value of this in a local context variable
function Example() {
var that = this;
// ...
function privateFunction() {
console.log(that);
}
this.publicFunction = function() {
privateFunction();
}
}
a more convenient way is to invoke Function.prototype.bind to bind a context to a function (forever). However, the only restriction here is that this requires a ES5-ready browser and bound functions are slightly slower.
var privateFunction = function() {
console.log(this);
}.bind(this);
I would say the proper way is to use prototyping since it was after all how Javascript was designed. So:
var Example = function(){
this.prop = 'whatever';
}
Example.prototype.fn_1 = function(){
console.log(this.prop);
return this
}
Example.prototype.fn_2 = function(){
this.prop = 'not whatever';
return this
}
var e = new Example();
e.fn_1() //whatever
e.fn_2().fn_1() //not whatever
Here's a fiddle http://jsfiddle.net/BFm2V/
If you're not using EcmaScript5, I'd recommend using Underscore's (or LoDash's) bind function.
In addition to the other answers given here, if you don't have an ES5-ready browser, you can create your own "permanently-bound function" quite simply with code like so:
function boundFn(thisobj, fn) {
return function() {
fn.apply(thisobj, arguments);
};
}
Then use it like this:
var Example = (function() {
function Example() {
var privateFunction = boundFn(this, function() {
// "this" inside here is the same "this" that was passed to boundFn.
console.log(this);
});
this.publicFunction = function() {
privateFunction();
}
}
return Example;
}()); // I prefer this order of parentheses
Voilà -- this is magically the outer context's this instead of the inner one!
You can even get ES5-like functionality if it's missing in your browser like so (this does nothing if you already have it):
if (!Function.prototype.bind) {
Function.prototype.bind = function (thisobj) {
var that = this;
return function() {
that.apply(thisobj, arguments);
};
}:
}
Then use var yourFunction = function() {}.bind(thisobj); exactly the same way.
ES5-like code that is fully compliant (as possible), checking parameter types and so on, can be found at mozilla Function.prototype.bind. There are some differences that could trip you up if you're doing a few different advanced things with functions, so read up on it at the link if you want to go that route.
I would say assigning self to this is a common technique:
function Example() {
var self = this;
function privateFunction() {
console.log(self);
}
self.publicFunction = function() {
privateFunction();
};
}
Using apply (as others have suggested) also works, though it's a bit more complex in my opinion.
It might be beyond the scope of this question, but I would also recommend considering a different approach to JavaScript where you actually don't use the this keyword at all. A former colleague of mine at ThoughtWorks, Pete Hodgson, wrote a really helpful article, Class-less JavaScript, explaining one way to do this.

How can jQuery do method chaining? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
how does jquery chaining work?
This is a normal thing you would see in a jQuery code:
$("div.selected").html("Blah.");
So, in the above code, in the function $(), it has a function called html(). And what I don't understand is, what I normally will do is:
funcA("blah"); //normal function, cool.
funcA.funcB("blah"); //normal function in an object, still cool.
and now this is confusing:
funcA("blah").funcB("blah") //huh??
How can funcB knows the arguments in funcA?
How can jQuery achieve this?
Thanks.
//function returning an object is a possibility. bar has access to elem because of
// the shared scope
function foo ( elem ) {
return {
bar : function () {
return elem.id;
}
};
}
In this one, the foo function returns an object containing whatever methods you wish. So when you call foo, you receive this:
{
bar : function () {
return elem.id;
}
}
elem is present from your call to foo. If you were to add a console.log( elem ) at the top of bar, you'd see that it's the same thing as what you passed to foo.
//this is kinda how jQuery does it:
var foo = (function() {
function foo ( elem ) {
this.elem = elem;
}
foo.prototype.bar = function () {
return this.elem.id;
};
return function ( elem ) {
return new foo( elem );
};
}());
This is a little more complex, and actually divided into two.
function foo ( elem ) {
this.elem = elem;
}
foo.prototype.bar = function () {
return this.elem.id;
};
Who doesn't love prototypical inheritance mixed with classical inheritance names? Anyway...functions act as both regular functions and as constructors. Meaning, when called with the new keyword, two special things happen:
this inside of the foo refers to a freshly made copy of foo.prototype
foo.prototype is returned (unless foo returns an object)
Note that foo.prototype isn't a magic value. It's just like any other object property.
So, inside the foo function/constructor, we're merely setting foo.prototype.elem, but not directly. Think of it like this (a little inaccurate, but it'll do): foo.prototype is the blueprint of a product. Whenever you wish to make more, you use the blueprint - duplicate what's inside, pass it along. Inside of foo, this refers to such a replication of the blueprint.
However, by explicitly setting values on foo.prototype, we're altering the blueprint itself. Whenever foo is called, it'll be called with this altered blueprint.
Finally, once foo is finished, the replication (the duplicated blueprint, but after foo has done stuff with it) is returned. This replication contains the original blueprint, and everything else we might have added - in this example, elem.
var foo = (function() {
...
return function ( elem ) {
return new foo( elem );
};
}());
We create a nameless function and immediately execute it.
(function () {
console.log( 'meep' );
}());
//is the equivalent of:
var something = function () {
console.log( 'meep' );
};
something();
something = undefined; //we can no longer use it
//and of this
function () {
console.log( 'meep' );
}(); //<--notice the parens
//however, it's considered good practice to wrap these self-executing-anonymous-functions
// in parens
Like all other functions, they can return values. And these values can be captured into variables.
var answer = (function () {
return 42;
}());
answer ==== 42;
var counter = (function () {
var c = 0;
return function () {
return c++;
};
}());
//counter is now a function, as a function was returned
counter(); //0
counter(); //1
counter(); //2...
So:
var foo = (function () {
...
return function ( elem ) {
...
};
}());
Returns a function which receives an argument, and that function is now assigned to foo.
The insides of the function:
return new foo( elem );
Is to ensure the special conditions I've spoken about above - it ensures that a new copy of the blueprint is manufactured, by explicitly doing the new operation. This can actually be replicated like this:
function foo ( elem ) {
this.elem = elem;
}
foo.prototype.bar = function () {...};
As long as you always call foo with the new keyword.
When you do funcA("blah").funcB("blah"), then funcB is called on whatever funcA returns. So you have funcA return some object that has a funcB, which is then called.
In the case of jQuery, most jQuery functions return the jQuery object, so function calls can be chained as much as you like. Many jQuery functions are designed to modify the contents of the jQuery object that is returned. So in your example, it's not the case that the call to html() "knows about" what was passed to the $() function. Rather, the $() function returns a jQuery object that points to the DOM elements that match the given selector. Further calls to functions on that jQuery object, then, will affect those selected elements.
Most functions in jquery return a jquery object which contains a set of elements. html doesn't know the arguments of $() exactly, it's more that the result of $() has a set of elements which are created based on the parameter passed to $().
In your example of funcA and funcB though, you could easily have funcA return an object which has a function named funcB. This object could also contain the value passed to funcA and then a call to funcB could "know" that value as well.
http://jsfiddle.net/ScENm/
function funcA(arg1) {
var enclosedVariable= arg1;
return {
funcB: function () {
alert(enclosedVariable);
}
};
}
Here is a quick and dirty example. ^^
funcA takes an argument and saves it then returns an object containing a single function. It has been "enclosed" and now funcB has access to this.
Technically you don't even have to save it... arg1 is available to funcB as well.
You should research chaining, it's what you're describing. You can google "jQuery chaining" to get started. Also check out jQuery's pluging tutorial for some more info
A function isn't anything special, you can return a function inside an object. For a quick example:
function $() {
return {
html: function() {
}
};
}
$().html(); // You just called the function!
jQuery doesn't have anything special in it. When you call a function in jQuery that doesn't return a value, it usually returns the jQuery object it was called on, like so:
var obj = {
doSomething: function() {
return this;
},
doSomethingElse: function() {
alert('Hi!');
}
};
obj.doSomething().doSomethingElse(); // Alerts "Hi!"
because again, it's just an object.
Chaining is generally done on the basis of the object that a method should return. If object A be an instance of class A and a method in it returns object A then the returned object can again be applied to the same class and this can be arranged in a chaining fashion. Or say object of class A returns object of class B then, the returned object can be applied to the method of class B.
objectOfA->methodOfA(arg)->methodOfB(args);
In this case if objectOfA->methodOfA(arg) returns object of class B and hence the method of class B can be called upon it and chained as above.
In your case,
$('div.selected').html('Blah ..')
Here $('div.selected') return a jquery element object(or array of object); upon which the method .html() can be applied since the method is only applicable to element object of jquery. It is just chaining as other programming languages do.
In case of PHP this case looks like,
$class->method1(argument)->method(2)
In this case, if class A has two methods method1 and method2 and method1 return the instance of its own then method 2 is again applicable to it.
This can be related to a function as well. Lets us suppose I have a function as such;
def function1(name):
return name
def function2(arg):
print len(name)
Now, this two functions can be chained simply as,
function2(function1('My Name is blah ...'))
Since the function1 returns a value, the type of the value must match to the input argument of function2 and this is how object work.

javascript singleton question

I just read a few threads on the discussion of singleton design in javascript. I'm 100% new to the Design Pattern stuff but as I see since a Singleton by definition won't have the need to be instantiated, conceptually if it's not to be instantiated, in my opinion it doesn't have to be treated like conventional objects which are created from a blueprint(classes). So my wonder is why not just think of a singleton just as something statically available that is wrapped in some sort of scope and that should be all.
From the threads I saw, most of them make a singleton though traditional javascript
new function(){}
followed by making a pseudo constructor.
Well I just think an object literal is enough enough:
var singleton = {
dothis: function(){},
dothat: function(){}
}
right? Or anybody got better insights?
[update] : Again my point is why don't people just use a simpler way to make singletons in javascript as I showed in the second snippet, if there's an absolute reason please tell me. I'm usually afraid of this kind of situation that I simplify things to much :D
I agree with you, the simplest way is to use a object literal, but if you want private members, you could implement taking advantage of closures:
var myInstance = (function() {
var privateVar;
function privateMethod () {
// ...
}
return { // public interface
publicMethod1: function () {
// private members can be accessed here
},
publicMethod2: function () {
// ...
}
};
})();
About the new function(){} construct, it will simply use an anonymous function as a constructor function, the context inside that function will be a new object that will be returned.
Edit: In response to the #J5's comment, that is simple to do, actually I think that this can be a nice example for using a Lazy Function Definition pattern:
function singleton() {
var instance = (function() {
var privateVar;
function privateMethod () {
// ...
}
return { // public interface
publicMethod1: function () {
// private members can be accessed here
},
publicMethod2: function () {
// ...
}
};
})();
singleton = function () { // re-define the function for subsequent calls
return instance;
};
return singleton(); // call the new function
}
When the function is called the first time, I make the object instance, and reassign singleton to a new function which has that object instance in it's closure.
Before the end of the first time call I execute the re-defined singleton function that will return the created instance.
Following calls to the singleton function will simply return the instance that is stored in it's closure, because the new function is the one that will be executed.
You can prove that by comparing the object returned:
singleton() == singleton(); // true
The == operator for objects will return true only if the object reference of both operands is the same, it will return false even if the objects are identical but they are two different instances:
({}) == ({}); // false
new Object() == new Object(); // false
I have used the second version (var singleton = {};) for everything from Firefox extensions to websites, and it works really well. One good idea is to not define things inside the curly brackets, but outside it using the name of the object, like so:
var singleton = {};
singleton.dothis = function(){
};
singleton.someVariable = 5;
The ES5 spec lets us use Object.create():
var SingletonClass = (function() {
var instance;
function SingletonClass() {
if (instance == null) {
instance = Object.create(SingletonClass.prototype);
}
return instance;
}
return {
getInstance: function() {
return new SingletonClass();
}
};
})();
var x = SingletonClass.getInstance();
var y = SingletonClass.getInstance();
var z = new x.constructor();
This is nice, since we don't have to worry about our constructor leaking, we still always end up with the same instance.
This structure also has the advantage that our Singleton doesn't construct itself until it is required. Additionally, using the closure as we do here prevents external code from using our "instance" variable, accidentally or otherwise. We can build more private variables in the same place and we can define anything we care to export publically on our class prototype.
The singleton pattern is implemented by creating a class with a method that creates a new instance of the class if one does not exist. If an instance already exists, it simply returns a reference to that object. 1
(function (global) {
var singleton;
function Singleton () {
// singleton does have a constructor that should only be used once
this.foo = "bar";
delete Singleton; // disappear the constructor if you want
}
global.singleton = function () {
return singleton || (singleton = new Singleton());
};
})(window);
var s = singleton();
console.log(s.foo);
var y = singleton();
y.foo = "foo";
console.log(s.foo);
You don't just declare the singleton as an object because that instantiates it, it doesn't declare it. It also doesn't provide a mechanism for code that doesn't know about a previous reference to the singleton to retrieve it. The singleton is not the object/class that is returned by the singleton, it's a structure. This is similar to how closured variables are not closures, the function scope providing the closure is the closure.
I am just posting this answer for people who are looking for a reliable source.
according to patterns.dev by Lydia Hallie, Addy Osmani
Singletons are actually considered an anti-pattern, and can (or.. should) be avoided in JavaScript.
In many programming languages, such as Java or C++, it's not possible to directly create objects the way we can in JavaScript. In those object-oriented programming languages, we need to create a class, which creates an object. That created object has the value of the instance of the class, just like the value of instance in the JavaScript example.
Since we can directly create objects in JavaScript, we can simply use
a regular object to achieve the exact same result.
I've wondered about this too, but just defining an object with functions in it seems reasonable to me. No sense creating a constructor that nobody's ever supposed to call, to create an object with no prototype, when you can just define the object directly.
On the other hand, if you want your singleton to be an instance of some existing "class" -- that is, you want it to have some other object as its prototype -- then you do need to use a constructor function, so that you can set its prototype property before calling it.
The latter code box shows what I've seen JS devs call their version of OO design in Javascript.
Singetons are meant to be singular objects that can't be constructed (except, I suppose, in the initial definition. You have one, global instance of a singleton.
The point of using the "pseudo constructor" is that it creates a new variable scope. You can declare local variables inside the function that are available inside any nested functions but not from the global scope.
There are actually two ways of doing it. You can call the function with new like in your example, or just call the function directly. There are slight differences in how you would write the code, but they are essentially equivalent.
Your second example could be written like this:
var singleton = new function () {
var privateVariable = 42; // This can be accessed by dothis and dothat
this.dothis = function () {
return privateVariable;
};
this.dothat = function () {};
}; // Parentheses are allowed, but not necessary unless you are passing parameters
or
var singleton = (function () {
var privateVariable = 42; // This can be accessed by dothis and dothat
return {
dothis: function () {
return privateVariable;
},
dothat: function () {}
};
})(); // Parentheses are required here since we are calling the function
You could also pass arguments to either function (you would need to add parentheses to the first example).
Crockford (seems to) agree that the object literal is all you need for a singleton in JavaScript:
http://webcache.googleusercontent.com/search?q=cache:-j5RwC92YU8J:www.crockford.com/codecamp/The%2520Good%2520Parts%2520ppt/5%2520functional.ppt+singleton+site:www.crockford.com&cd=1&hl=en&ct=clnk
How about this:
function Singleton() {
// ---------------
// Singleton part.
// ---------------
var _className = null;
var _globalScope = null;
if ( !(this instanceof arguments.callee) ) {
throw new Error("Constructor called as a function.");
}
if ( !(_className = arguments.callee.name) ) {
throw new Error("Unable to determine class name.")
}
_globalScope = (function(){return this;}).call(null);
if ( !_globalScope.singletons ) {
_globalScope.singletons = [];
}
if ( _globalScope.singletons[_className] ) {
return _globalScope.singletons[_className];
} else {
_globalScope.singletons[_className] = this;
}
// ------------
// Normal part.
// ------------
var _x = null;
this.setx = function(val) {
_x = val;
}; // setx()
this.getx = function() {
return _x;
}; // getx()
function _init() {
_x = 0; // Whatever initialisation here.
} // _init()
_init();
} // Singleton()
var p = new Singleton;
var q = new Singleton;
p.setx(15);
q.getx(); // returns 15
I stole this from CMS / CMS' answer, and changed it so it can be invoked as:
MySingleton.getInstance().publicMethod1();
With the slight alternation:
var MySingleton = { // These two lines
getInstance: function() { // These two lines
var instance = (function() {
var privateVar;
function privateMethod () {
// ...
console.log( "b" );
}
return { // public interface
publicMethod1: function () {
// private members can be accessed here
console.log( "a" );
},
publicMethod2: function () {
// ...
privateMethod();
}
};
})();
singleton = function () { // re-define the function for subsequent calls
return instance;
};
return singleton(); // call the new function
}
}

Categories

Resources