There are two ways of creating an object in javascript:
use new on a "constructor function"
return a dictionary {} and set the proper key/value pairs
The first is, for example
FooType = function() {
this.hello = function() { alert("hello"); };
};
foo = new FooType();
foo.hello();
the second is
fooFactory = function() {
return {
hello : function() { alert("hello"); }
};
};
foo = fooFactory();
foo.hello();
(Code written for the post. not guaranteed correct)
Apart from risks of mistakes of having this bound to the global object, are these two method totally equivalent (also considering prototype inheritance etc...)?
They're not equivalent, especially when considering prototype inheritance.
FooType = function() {
this.hello = function() { alert("hello"); };
};
var foo = new FooType();
FooType.prototype.bye = function() { alert('bye!'); };
foo.bye(); // "bye!"
The only way you could achieve that in the fooFactory way would be to add it to the object prototype which is a Very Bad Idea.
The first method is much more meaningful in my opinion (since the object has a type you can check against) and can offer much better performance if the prototype is done properly. In your first example, every time you instantiate a new FooType object, it create a new "hello" function. If you have lots of these objects, that's a lot of wasted memory.
Consider using this instead:
function FooType() { }
FooType.prototype.hello = function() {
alert('Hello');
};
In example one, foo inherits from FooType's prototype (which hasn't had any changes). foo instanceof FooType is true in the example. In example two, there's no inheritance. If you are going to be reusing methods, use example one but define shared methods on FooType.prototype, not in the function body:
var FooType = function() {};
FooType.prototype.hello = function() { alert("hello"); };
Related
I am curious as what else the new keyword does in the background apart from changing what the this scope refers too.
For example if we compare using the new keyword to make a function set properties and methods on an object to just making a function return a new object, is there anything extra that the new object does?
And which is preferred if I don't wish to create multiple objects from the function constructor
var foo2 = function () {
var temp = "test";
return {
getLol: function () {
return temp;
},
setLol: function(value) {
temp = value;
}
};
}();
var foo = new function () {
var temp = "test";
this.getLol = function () {
return temp;
}
this.setLol = function(value) {
temp = value;
}
}();
The firebug profiler tells me using the new keyword is slightly faster (2ms instead of 3ms), on large objects is new still significantly faster?
[Edit]
Another matter is on really large object constructors is having a return at the bottom of the function (It will have a large amount of local functions) or having a few this.bar = ... at the top of the function more readable? What is considered a good convention?
var MAIN = newfunction() {
this.bar = ...
// Lots of code
}();
var MAIN2 = function() {
// Lots of code
return {
bar: ...
}
}();
Quoting Douglas Crockford from the Good Parts book (page 47), to answer the title of this question:
If the new operator were a method instead of an operator, it could be implemented like this:
Function.method('new', function () {
// Create a new object that inherits from the
// constructor's prototype.
var that = Object.create(this.prototype);
// Invoke the constructor, binding -this- to
// the new object.
var other = this.apply(that, arguments);
// If its return value isn't an object,
// substitute the new object.
return (typeof other === 'object' && other) || that;
});
The Function.method method is implemented as follows. This adds an instance method to a class (Source):
Function.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
};
Further reading:
Mozilla Dev Center: Object.create()
Mozilla Dev Center: Function.apply()
Douglas Crockford: Classical Inheritance in JavaScript
Read the spec. Sections 11.2.2 and 13.2.2 are relevant and aren't too tricky to understand (note that the latter two links are to non-official HTML-ified version of the spec).
In summary, if you have a function f that returns an object, the only observable difference that calling it with new will make is that the this value will be different, and that calling it with new may be slower, since it involves additional steps of creating an object and assigning it a few properties.
I'd like to have an object with multiple levels of methods and properties. The top level will have properties and methods. Some of these properties will then act as name-spaces for second level methods and properties.
e.g.
//first level methods
base.doStuff();
base.doMore();
//second level methods
base.level2.doStuff();
Doing the first level is straight forward:
function Base(foo) {
this.foo = foo;
}
Base.prototype.doStuff = function () {
console.log(this.foo);
}
Base.prototype.doMore = function () {
console.log(this.foo);
}
base = new Base("bar");
base.doStuff();
Is it possible to get a second level, where in the function expression the "this" keyword points back to the Base constructor?
It's much easier to do this without prototypes:
function Base() {
var base = this;
base.level2 = {
moreStuff: function() {
// use "base" instead of "this" here
}
};
}
This can be combined with either prototypical methods, as in your example, or methods defined directly on base in the constructor. The downside of this is that you are creating the method functions every time you instantiate a new object, so you miss some of the shared-prototype goodness of standard prototypical methods.
You could create a new prototype-based object to be your level2:
function Level2() {}
Level2.prototype.moreStuff = function() {
// do stuff
}
function Base() {
this.level2 = new Level2();
}
But the methods of base.level2 won't be bound to base unless you bind them explicitly. Various libraries have bind support (e.g. Underscore's _.bind), or you can do it in plain JS:
function Base() {
var base = this;
base.level2 = new Level2();
base.level2.moreStuff = function() {
return Level2.prototype.moreStuff.apply(base, arguments);
}
}
You could further simplify here, but you're always going to have to make new methods bound in one way or another, because JS is never going to assign this in base.level2.moreStuff() to base without explicit binding - so in most cases the first option is the easiest and cleanest.
But really, is it worthwhile just for namespacing? If there's no functional value, it's a lot harder than simply calling your methods level2MoreStuff(), etc.
Well,
base.doStuff();
is calling doStuff in context of base. It is the same as
base.doStuff.call(base);
You can call and apply any function, for overriding this:
var base = new Base();
var someFun = function () {
console.log (this === base); // true
};
someFun.call(base);
Further anonymous example:
var anObj = {
method0: function () {
console.log (this === anObj); // true
}
};
anObj.method1 = function () {
console.log (this === anObj); // true
};
anObj.method0();
anObj.method1();
So the "second level" points this to level2, not to the "first level" object.
This is a really bad idea, but here goes:
function Base() {
this.name = 'Base';
this.level2 = new Level2(this);
}
Base.prototype.whatsMyName = function(){
alert(this.name);
};
function Level2(base) {
this.name='Level2';
for(var func in Level2.prototype) {
this[func] = Level2.prototype[func].bind(base);
}
}
Level2.prototype.whatsMyName = function(){
alert(this.name);
};
var b = new Base();
b.whatsMyName(); //Base
b.level2.whatsMyName(); //Also Base
You can see it running here: http://jsfiddle.net/zLFgd/1/
After reading a lot of articles on singleton pattern, and making some tests, I found no difference between the singleton pattern like this (http://jsfiddle.net/bhsQC/1/):
var TheObject = function () {
var instance;
function init() {
var that = this;
var foo = 1;
function consoleIt() {
console.log(that, foo);
}
return {
bar: function () {
consoleIt()
}
};
}
return {
getInstance: function () {
if (!instance) {
instance = init();
}
return instance;
}
};
}();
var myObject = TheObject.getInstance();
myObject.bar();
and code like this (http://jsfiddle.net/9Qa9H/3/):
var myObject = function () {
var that = this;
var foo = 1;
function consoleIt() {
console.log(that, foo);
}
return {
bar: function () {
consoleIt();
}
};
}();
myObject.bar();
They both make only one instance of the object, they both can have "private" members, that points to window object in either of them. It's just that the latter one is simpler. Please, correct me if I'm wrong.
Using standard constructor like this (http://jsfiddle.net/vnpR7/2/):
var TheObject = function () {
var that = this;
var foo = 1;
function consoleIt() {
console.log(that, foo);
}
return {
bar: function () {
consoleIt();
}
};
};
var myObject = new TheObject();
myObject.bar();
has the advantage of correct usage of that, but isn't a singleton.
My question is: what are the overall advantages and disadvantages of these three approaches? (If it matters, I'm working on a web app using Dojo 1.9, so either way, this object will be inside Dojo's require).
Well, the real difference is the time of construction of the singleton. The second approach creates the singleton right away, the first only after being called the first time. Depending on what the singleton needs in memory, this might make a difference for your application. For example, you might need the singleton only if a user performs a certain action. So if the user does not do it, then it would be nice not to have to initialise the singleton at all.
Also, if the initialisation of the singleton is computationally intense, it is a good thing to be able to defer that until you really need the singleton.
Edit: And as Jani said, the last one isn't a singleton, so i didn't discuss it.
I don't think there's really a big practical difference between the first two.
The first one with getInstance behaves more like a singleton pattern in classical OOP languages like Java.
The second approach behaves more like a static class in classical OOP languages.
Obviously the issues both of these have are the same all singletons have (plenty of material for this if you look it up on google).
The last approach is not really even using new - you're returning an object from the "constructor". Obviously this one is not a singleton at all, and as such, would be the preferred approach.
I like to build singletons likes this:
function FriendHandler(){
if(FriendHandler.prototype.singleton){
return FriendHandler.prototype.singleton;
}
if(!(this instanceOf FriendHandler)){
return new FriendHandler();
}
FriendHandler.prototype.singleton = this;
...
this.selectFriends = function(firstName){
...
};
}
If you do:
new FriendHandler()
or
FriendHandler()
It always returns the same instance.
I wrote about it some months ago: http://franciscomsferreira.blogspot.com/2013/01/how-to-write-maintainable-javascript-or.html
Basically I want inheritable functions as in
Base = function() { };
Base.prototype.foo = function() {
console.log("base foo");
};
Derived = function() { };
somelib.inherit(Derived, Base);
Derived.prototype.foo = function() {
console.log("derived foo");
}
d = new Derived():
d.foo();
And I want it to print
derived foo
base foo
Yes I know I can explicitly call Base.prototype.foo.call(this); I'm just wondering if there is a pattern for calling overridden super class functions automatically. The problem I'm trying to solve is 2 fold.
derived classes should NOT have to remember to call their parent's method, it just happens automatically.
if 1. can't happen then at least I'd like Derived not to call Base by name since that's brittle. Rather I'd like it call parentclass or something so you don't have to know the base. That way if you change the name of the base you don't have to go fixing every derived class.
You can implement such functionality by using a structure like:
function Base(){}
Base.prototype.destroy = function(){console.log('Base destroy');};
function Derived(){}
Derived.prototype = new Base; // Let Derived inherit from Base
// Override the `destroy` method
Derived.prototype.destroy = function() {
console.log('Derived destroy');
// Call parent class method
this.constructor.prototype.destroy();
// If the context of the method is important, you can use Function.call:
//this.constructor.prototype.destroy.call(this);
};
// Create an instance of Derived, and call the destroy method:
(new Derived).destroy();
I would suggest thinking about exactly why you are doing this, at least in terms of requirement #1. Keep in mind that your desired pattern would take away a great deal of flexibility. For instance, if you have a situation where you want to print the statements in the opposite order:
base foo
derived foo
You would either have to abandon your pattern or create a function foo2() in the derived class which then calls foo() in the base class. Neither is very pretty.
Same goes if you even want to do something as simple as:
derived foo
base foo
one more thing in the derived function
I would contend that using this pattern may work for the exact thing you want to do right now, but may give you fits when you want to make a seemingly trivial change down the road. All to save one line of code!
As far as I know there is no language integrated destructor functionality in JavaScript. It is all about frameworks. If you are using ASP.NET Ajax, for example, the framework would expect that your objects would have a dispose method, responsible for freeing up resources (event handlers). So, it is up to you.
Ok, this isn't quite what you are looking for, in that it's not a "pattern", but it is a potential implementation path you could follow:
Take a look # the MooTools Class.Extras package (for lack of a better word). Using the Chain Class, you could probably get the desired functionality.
var parent = (function () {
var construct = function () {
};
construct.prototype = {
constructor: construct,
destroy: function () {
console.log('parent destruction');
}
}
return construct;
})();
var child = (function (parent) {
var construct = function () {
};
construct.prototype = Object.create(parent.prototype);
construct.prototype.constructor = construct;
construct.prototype.destroy = function () {
parent.prototype.destroy.call(this); // calling parent, too
console.log('child destruction');
};
return construct;
})(parent);
child_instance = new child();
child_instance.destroy();
I would prefer a way where I don't assign Derived = chainify() so that the api would be the same as you had in your question but as of right now this is the best way I can get it to work. It works by replacing each method of the object with a method that calls the replaced method and travels up the parent chain calling their methods along the way.
function chainify() {
return function () {
var property;
for (property in this) {
if (typeof this[property] === "function") {
this[property] = chain(this[property], property);
}
}
function chain(method, method_name) {
return function() {
method();
var current = this;
while (current = current.parent) {
if (current.hasOwnProperty(method_name)) {
current[method_name].apply(this, arguments);
}
}
};
}
}
}
var somelib = function() { };
somelib.inherit = function (derive, base) {
derive.prototype = new base;
derive.prototype.parent = base.prototype;
};
var Base = function() { };
Base.prototype.foo = function() {
console.log("base foo");
};
var Derived = chainify();
somelib.inherit(Derived, Base);
Derived.prototype.foo = function() {
console.log("derived foo");
};
d = new Derived();
d.foo();
I am curious as what else the new keyword does in the background apart from changing what the this scope refers too.
For example if we compare using the new keyword to make a function set properties and methods on an object to just making a function return a new object, is there anything extra that the new object does?
And which is preferred if I don't wish to create multiple objects from the function constructor
var foo2 = function () {
var temp = "test";
return {
getLol: function () {
return temp;
},
setLol: function(value) {
temp = value;
}
};
}();
var foo = new function () {
var temp = "test";
this.getLol = function () {
return temp;
}
this.setLol = function(value) {
temp = value;
}
}();
The firebug profiler tells me using the new keyword is slightly faster (2ms instead of 3ms), on large objects is new still significantly faster?
[Edit]
Another matter is on really large object constructors is having a return at the bottom of the function (It will have a large amount of local functions) or having a few this.bar = ... at the top of the function more readable? What is considered a good convention?
var MAIN = newfunction() {
this.bar = ...
// Lots of code
}();
var MAIN2 = function() {
// Lots of code
return {
bar: ...
}
}();
Quoting Douglas Crockford from the Good Parts book (page 47), to answer the title of this question:
If the new operator were a method instead of an operator, it could be implemented like this:
Function.method('new', function () {
// Create a new object that inherits from the
// constructor's prototype.
var that = Object.create(this.prototype);
// Invoke the constructor, binding -this- to
// the new object.
var other = this.apply(that, arguments);
// If its return value isn't an object,
// substitute the new object.
return (typeof other === 'object' && other) || that;
});
The Function.method method is implemented as follows. This adds an instance method to a class (Source):
Function.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
};
Further reading:
Mozilla Dev Center: Object.create()
Mozilla Dev Center: Function.apply()
Douglas Crockford: Classical Inheritance in JavaScript
Read the spec. Sections 11.2.2 and 13.2.2 are relevant and aren't too tricky to understand (note that the latter two links are to non-official HTML-ified version of the spec).
In summary, if you have a function f that returns an object, the only observable difference that calling it with new will make is that the this value will be different, and that calling it with new may be slower, since it involves additional steps of creating an object and assigning it a few properties.