Let us say I have the following:
var foo = (function(){
var bar = 0;
return {
getBar: function(){
return bar;
},
addOne: function(){
bar++;
},
addRandom: function(rand){
bar += rand;
}
}
})();
And I have the following:
var foo2 = function(){
var bar = 0;
this.getBar = function(){
return bar;
};
this.addOne = function(){
bar++;
};
this.addRandom = function(rand){
bar += rand;
}
};
Is the only difference in executing the functions a new?
alert(foo.getBar()); //0
foo.addOne();
foo.addRandom(32);
alert(foo.getBar()); //33
var foo2_obj = new foo2;
alert(foo2_obj.getBar());//0
foo2_obj.addOne();
foo2_obj.addRandom(32);
alert(foo2_obj.getBar());//33
They both out put the exact same thing.
So what is the difference in the long run?
What can one do that the other cannot?
Fiddle Demo of the above: http://jsfiddle.net/maniator/YtBpe/
In the first one you can only create the object once, while with the second one you can create as many objects as you like. I.E. the first one is effectively a singleton.
Note that closures are not ok for the second one. Every time you instantiate it you are creating the functions all over again and waste a ton of memory. The prototype object is intended to counter this, where you can create the functions once outside a function scope and no accidental closures are created.
function foo2(){
this._bar = 0;
}
foo2.prototype = {
constructor: foo2,
getBar: function(){
return this._bar;
},
addOne: function(){
this._bar++;
},
addRandom:function(rand){
this._bar += rand;
}
};
Then:
var a = new foo2, b = new foo2, c = new foo2;
Creates three instances which have their own _bar but share the same functionality.
jsperf
You can "compare" all of this to PHP, some of the code won't even run but it's "equivalent" in principle:
var foo = (function(){
var bar = 0;
return {
getBar: function(){
return bar;
},
addOne: function(){
bar++;
},
addRandom: function(rand){
bar += rand;
}
}
})();
is roughly "equivalent" to this in PHP:
$foo = new stdClass;
$foo->bar = 0;
$foo->getBar = function(){
return $this->bar;
};
$foo->addOne = function(){
$this->bar++;
}
$foo->addRandom = function($rand){
$this->bar += $rand;
}
var foo2 = function(){
var bar = 0;
this.getBar = function(){
return bar;
};
this.addOne = function(){
bar++;
};
this.addRandom = function(rand){
bar += rand;
}
};
Is roughly "equivalent" to this in PHP:
Class foo2 {
public function __construct(){
$bar = 0;
$this->getBar = function(){
return $bar;
};
$this->addOne = function(){
$bar++;
};
$this->addRandom = function($rand){
$bar += rand;
};
}
}
function foo2(){
this._bar = 0;
}
foo2.prototype = {
constructor: foo2,
getBar: function(){
return this._bar;
},
addOne: function(){
this._bar++;
},
addRandom:function(rand){
this._bar += rand;
}
};
Is roughly "equivalent" to this in PHP:
Class foo2 {
public $_bar;
public function __construct(){
$this->_bar = 0;
}
public function getBar(){
return $this->_bar;
}
public function addOne(){
$this->_bar++
}
public function addRandom($rand){
$this->_bar += $rand;
}
}
...and is the only one that is close to OOP in the three above examples
The only difference is that foo will be a generic Object, whereas foo2_obj will identify as a foo2 when checking its type (i.e. foo2_obj.constructor == foo2 will be true, while the equivalent on foo is foo.constructor == Object).
Of course, there's an important distinction between foo and foo2 - foo is an object, while foo2 is a function (intended for use as a constructor). Thus, it is trivial to make as many instances of foo2 (of which foo2_obj is one), while the idea of creating "instances" of foo doesn't really make sense - the best you could do are copies (which is more difficult than calling a constructor).
Due to the copying/creating instances distinction, the second approach allows for real OO programming with prototype chains, while the first makes such things much more difficult (and ill-advised).
[1]first,but not important:efficiency
function Foo1() {
var bar = 0;
return {
getBar: function () {
return bar;
}
}
}
var o = Foo1();
o.getBar();
function Foo2() {
var bar = 0;
this.getBar = function () {
return bar;
}
}
var o = new Foo2();
o.getBar();
which is the faster?,look object-literal-vs-new-operate
[2]program pattern:the former has no program pattern,but the latter will benefit form prototypal inheritance.if now we want to add a method named "logBar",
former:
1:extend every Foo1 instance:
o.logBar = function () {
console.log(this.getBar());
}
o.logBar();
bad way!
2:find where Foo1 defined and add:
function Foo1() {
var bar = 0;
return {
getBar: function () {
return bar;
},
logBar:function () {
console.log(this.getBar());
}
}
}
var o = Foo1();
o.logBar = o.logBar();
would you want to go back to do this when you want to add more method ervey time?
latter:
Foo2.prototype.logBar = function () {
console.log(this.getBar());
}
var o = Foo2();
o.logBar = o.logBar();
this would be work fine.
[3] back to efficiency:
in Foo1's way,it product logBar function instance ervey time when a Foo1 instance created.object-literal-vs-new-operate
I think in my personal view of this two types
1- Singleton
2- Object
Let's we say we have one page having their javascript using Object (Second), and
having many utils using singletons (First), and works fine.
But one day we need a new page that call the first page via AJAX, this new page have their javascript using Object (Second) and have the same utils using singleton, but we add some new functions in the utils singletons.
Turns out, the utils singletons in the new page are overriden for the loaded utils singletons in the first page, So when the new page execute some of those new function doesn't exist, generating errors ...
I think this is my point, the singletons are overriden when you have this scenario, and find erros in cases like this are hard.. hard..., diferent from a object that have unique instances
Cheers.
The main difference is actually that foo is an object, whereas foo2 is a function.
That means that you'll not be able to create another object like foo that is not actually foo itself, except if you copy/paste its code.
On the other hand, you can create another foo2 object and manipulate it while using foo2_obj for another purpose.
To make short, foo is an instance while foo2 can bee seen as a class (even if it's just a function constructing an object).
It depends on what you want to do in your program, but I'd surely recommend to use the 2nd form which is allowing to reuse your code by creating other instances.
foo and foo2_obj They are the same. In both cases you have a function that creates a new object, references a variable in closure scope and returns that object.
You have 4 things
anonymous function that is a factory for "foos"
object foo created from anonymous factory
foo2 which is a name factory for "foo2_objs"
object foo2_obj created from foo2 factory
The exact difference between using new and returning function literals from a function is neglible if you don't touch <Function>.prototype
You probably want to compare
var foo2 = function(){
var bar = 0;
this.getBar = function(){
return bar;
};
this.addOne = function(){
bar++;
};
this.addRandom = function(rand){
bar += rand;
};
};
To
var Foo = {
addOne: function () { this.bar++; },
addRandom: function (x) { this.bar+=x; }
};
var foo3 = function () {
return Object.create(Foo, { bar: { value: 0 } });
}
foo3 uses prototypical OO. this means you don't have to recreate those functions all the time.
In simple terms if you are creating 10 instances of foo and foo2, the getBar function of foo will exists 10 times in memory and that of foo2 will be only once.
Also, modern browsers like chrome with V8 compiler, it compiles the js to machine code... in that case foo2 will get translated to a native class object and its like a 20 times faster (when you create say 1000 instances in a loop)
I normally uses the simple object method when there is only once instance of that class/module is needed. The structure that I follow is,
var myInstance = function(){
var self = {};
self.bar = null;
self.gerBar = function(){
return self.bar
}
return self;
}();
this is quite similar to the foo approach, but I find this structure more handy.
One other difference (in practical use) that i normally encounter is when I have callback functions or timeouts inside the class,
var foo2 = function(){
this.doSomething = function(){
var temp = this;
$.someAsyncCall(function(){
// 'this' in current scope is the inline function itself, not the class instance
// so have to store the instance ref in a local var in outer scope and then use that to get the class instance
temp.callAfterAsyncCall();
});
};
this.callAfterAsyncCall = function(){
};
};
as you can see the local temp variable is not pretty when you have a lot these cases.
where in the other approach, you always the the self reference everywhere inside the module scope,
var myInstance = function(){
var self = {};
self.doSomething = function(){
$.someAsyncCall(function(){
self.callAfterAsyncCall();
});
}
self.callAfterAsyncCall = function(){
};
return self;
}();
I not sure if its important for you, but just thought worth mentioning.
Related
I have read this answer and IIFE but I can't seem to find the correct solution to my problem.
I have a simple class here:
define(['jquery'], function($) {
// Need 'self' because someCallback() is being called with .call() and 'this' changes
var self;
function Foo(number) {
self = this;
this.someNumber = number;
}
Foo.prototype = {
someCallback: function () {
//Use self because 'this' changes to a DOM element
var num = self.someNumber;
//Do something with the num
return num * 2;
}
};
return Foo;
});
and someCallBack() is being called by a jQuery plugin using .call(). Because of this, the context changed, hence the use of the self variable.
However, this is wrong because:
define(['foo'], function(Foo) {
describe('context question', function () {
var foo1 = new Foo(1);
var foo2 = new Foo(2);
it('"this" should work', function () {
var call1 = foo1.someCallback.call(this); // 4
var call2 = foo2.someCallback.call(this); // 4
expect(call2).toBe(4); // Only works because it is 'new' last
expect(call1).toBe(2); // Fails because 'self' is taken from foo2
});
});
});
How exactly should I wrap the self variable to make this code work?
You could probably just use the revealing module pattern and declare it as a "global" variable (local to the module):
define(['jquery'], function($) {
var someNumber;
function Foo(number) {
someNumber = number;
}
Foo.prototype = {
someCallback: function () {
return someNumber * 2;
}
};
return Foo;
});
Two ways of calling an object method which stores its own this value include
Define the method as a nested function which references its this value in a closure which stores this value in a variable. The function defined could be anonymous or declared with a name but must be evaluated each time a class instance is created, so as to create a new Function object capturing different values of self in function scope.
Take a statically defined function object and bind its this value using bind. Bind creates a new wrapper function object each time it is called.
The first method looks like (without Jquery or Jasmine):
function Foo(number)
{ var self = this;
this.num = number;
this.someCallback = function() // method with new Foo object stored as self in function scope
{ // something with num:
return self.num * 2;
}
}
and the second method could look like
function Foo(number)
{ this.num = number
this.someCallback = this.someCallback.bind(this); // bind prototypical method as local method.
}
Foo.prototype = {
someCallback: function () {
// this value is bound by constructor;
//Do something with the num
return this.num * 2;
}
};
I have a class-like function
var myapp = function() {
this.method = function() {
//Do something...
}
}
To reference myapp from within methods, the first line in the myapp function is
var self = this;
So a method in myapp can reference the "class" safely
this.anothermethod = function() {
self.method();
}
The full code:
var myapp = function() {
var self = this;
this.dosomething = function(Callback) {
Callback();
}
this.anothermethod = function() {
//Pass a callback ("self" is required here)...
this.dosomething(function() {
self.complete();
)};
}
this.complete = function() {
console.log('All done!');
}
}
My question is: can I assign var self = this; from outside the declaration of myapp? I don't want to set self every single time I write a "class".
Kind of like this:
var library = function() {
this.loadclass = function(Name) {
var tempclass = window[Name];
library[Name] = new tempclass();
library[Name].self = library[Name];
}
}
var myapp = new library();
myapp.loadclass('myapp');
myapp.myapp.dosomething();
It doesn't work as expected. self equals window for some reason.
I know it's a little abnormal programming, but can it be done?
Note about using self: I remember why I started using it. I wanted to reference the base class (this) from within callbacks inside methods. As soon as you try to use this within a function within a method, it then references the method, not the base class.
Unless you are detaching the methods from the object and calling them as plain functions, you don't need a self variable at all. The method can reach its object using the this keyword:
var myapp = function() {
this.method = function() {
//Do something...
}
this.anothermethod = function() {
this.method();
}
}
No, you can't really; not the way you're creating objects at least.
You can sort of do this, by enumerating all the functions on the object and binding them to the object itself. Something like this:
Object.keys(obj)
.filter(function(n) { return typeof obj[n] == "function" })
.forEach(function(n) { obj[n] = obj[n].bind(obj) })
This function will go over the public, enumerable properties of obj and make sure that any functions on it are bound to obj; i.e. this is now bound to obj.
A primer on this
When you call new, this within the constructor gets bound to the newly created object. If you do need a reference to this as it was bound at constructor time, you do need to keep away a reference to it.
Functions in JavaScript are bound to wherever it is called. Here's an example:
var foo = new function() {
this.bar = function() {
return 'bar'
}
this.baz = function() {
return this.bar()
}
}
console.log(foo.bar()) // bar
console.log(foo.baz()) // bar
var bar = function() {
return "window"
}
var baz = foo.baz
console.log(baz()) // window
When we call foo.baz() it'll look to foo for the implementation of bar, but when calling foo.baz through a "detached" reference, it'll look to whatever the global object is (in this case the browser window object) and call bar from there. Because we defined bar in the global context, it then returns window.
The practice of assign a variable called self is so that it doesn't matter how you call your methods, because you always reference the this at the time of creation through the self variable. You don't have to write things this way, but then you should understand that references to this may change under your feet.
Consider the Following Example
var Foo = function(){
this.identity = 'Foo';
};
Foo.prototype.bar = function(){
this.identity = 'bar';
};
var fooInstance = new Foo(),
bar = new fooInstance.bar();
Question
Within bar, how may I obtain the fooInstance variable? Is there a way for a child of Foo to recognize its parent as fooInstance? For example, how could I create a function in bar that would return fooInstance. A slight caveat is that bar must by created using the prototype command and cannot simply be nested in Foo to access any Foo instances that way.
My Ideas and Why They Don't Work
It would be possible to rewrite the functions like so
var Foo = function(){
this.identity = 'Foo';
};
Foo.prototype.createBar = function(){
var parent = this;
function bar(){
this.parent = parent;
this.identity = 'bar';
};
return new bar();
};
var fooInstance = new Foo(),
bar = fooInstance.createBar();
Yet for the purposes of creating easily readable code i would rather not use this approach if not needed.
Further Clarification
Let me put the question in context. I am prototyping on CanvasRenderingContext2D so that all contexts for the canvas element will contain my new method. Lets call that method foo and assume context is a created canvas context. How create a variable like so "new context.foo()" such that the foo function can use the context variable?
If you need to reference the fooInstance object from the bar object, you could use dependency injection like this:
Foo.prototype.bar = function(fooInstance) {
this.identity = 'bar';
this.fooInstance = fooInstance;
};
var fooInstance = new Foo(),
bar = new foo.bar(fooInstance);
You could simplify the creation process by implementing a factory function on Foo.
Foo.prototype.createBar = (function() {
function Bar(parent){
this.parent = parent;
this.identity = 'bar';
};
return function () {
return new Bar(this);
};
})();
var fooInstance = new Foo(),
bar = fooInstance.createBar();
how could I create a function in bar that would return fooInstance
If that function is called as a constructor (with new), you can't really do it. The this keyword, the only reference to the "parent" (the object on which you called the method) is set to the new instance in a constructor invocation. You can get the reference only with a closure, for example by creating the constructor in the parent's constructor function (which doesn't work for you) or by returning the constructor from a closure on the prototype (which you nearly got in the second example):
Foo.prototype.getBarCoonstructor = function() {
var parentFoo = this;
return function Bar() {
// constructor things
// using "parentFoo" reference
};
};
// Usage:
var bar = new (foo.getBarConstructor()) (); // ugly.
Instead of creating new constructors for every call of getBarConstructor, you better should put it outside of the method and put parentFoo as an argument to it. Your idea was already quite good.
function Bar(parent) {
// constructor things, referring "parent"
}
Bar.prototype.… = …;
Foo.prototype.createBar = function() {
return new Bar(this); // passing the Foo instance
};
(#plalx has the same solution, but wrapped in a module closure)
Foo.prototype.bar is simply a function on the prototype Object of Foo. There is no way for that function to know of its 'parent' unless you explicitly define it in its scope chain.
I.e. if you would do
var Foo = function(){
this.identity = 'Foo';
};
var fooInstance = new Foo();
Foo.prototype.bar = function(){
console.log(fooInstance); // retrieve from scope
this.identity = 'bar';
};
bar = new foo.bar();
that would work.
Very simple question, not sure if there are any differences in these ways of creating a javascript "module". I'm hoping somebody can clarify it for me.
A)
var foo = function() {
var bar = function() {
console.log('test');
};
return {
bar: bar
};
};
B)
var foo = function() {
function bar() {
console.log('test');
};
return {
bar: bar
};
};
C)
var foo = function() {
this.bar = function() {
console.log('test');
};
return {
bar: this.bar
};
};
A and B are essentially the same, though there is a very minor difference between A and B due to function/variable hoisting, theoretically you could write code which would work in B but break in A, but practically speaking you'd have to really write weird code to do so.
C will work, but is conceptually wrong. The point of using this.funcName in a function is as a constructor (creating lots of objects using new Thing(). If you aren't using the function as a constructor you shouldn't be using that style as someone scanning the code may mistake the function as a constructor instead of its actual purpose which is a module.
At first, you forgot to execute the function expression: the module pattern is an IEFE. You just create a function.
Your last example is nonsense, it looks like a constructor function when assigning properties to this - and when executed as a IEFE it breaks (and using it with new has undesired effects; an when returning an object it's useless).
For the difference between the first and the second snippet see var functionName = function() {} vs function functionName() {}. In context of the module pattern, the function declaration is recommended.
//Javascript Module Pattern
var person = (function() {
var cname = 'CheapFlight';
return {
name: "Santosh Thakur",
getAge: function() {
return cname;
},
growOlder: function() {
return cname + " Updated";
}
};
}());
person.cname = "New Company"
console.log(person.cname);
console.log(person.name);
console.log(person.getAge());
console.log(person.growOlder());
prefix var before a function makes it a "class"-ish, this means you can make many versions of it. This goes for A
For example:
var hi = function()
{
var bye = function()
{
alert("bye");
}
bye(); // this will call bye
var something = new bye(); // this will create a new instance of bye();
}
var something = new hi();
something();
B means you can only call bar, not make a new instance of it inside the function.
C is the same as bar because of its scope
Class-ish:
var Dog = function( hair, type )
{
this.hair = hair;
this.type = type;
}
var fred = new Dog( "long", "Dalmation" );
alert( fred.hair );
var dave = new Dog( "short", "Poodle" );
alert( dave.type);
This is a class ^
I'm fairly certain this isn't possible, but wanted to see if anyone had some ingenious ideas as to how to make it possible.
I want the following code to work:
var x = new foo();
x.a.getThis() === x; // true
In other words, I want x.a.getThis to have a reference to this being x in this case. Make sense?
In order to get this to work one level deep is simple:
function foo(){}
foo.prototype.getThis = function(){ return this; }
var x = new foo();
x.getThis() === x; // true
One thing, I want this to work as a prototype, no "cheating" by manually binding to this:
function foo(){
this.a = {
getThis : (function(){ return this; }).bind(this)
};
}
Although the above is a perfect functional example of what I'm trying to achieve, I just don't want all the extra functions for each instance :)
FYI, the actual use case here is that I'm creating classes to represent Cassandra objects in node and I want to be able to reference a super-column --> column-family --> column via foo.a.b and keep a reference to foo in the deep function.
You can't do this without a forced bind of some kind. You say you don't want to "cheat" but this breaks the standard rules about what this is, so you have to cheat. But JS lets you cheat, so it's all good.
BTW, for what it's worth coffee script makes this so trivial.
foo = ->
#a = getThis: => this
The fat arrow => preserves the context of this for from the scope it was called in. This allows you to easily forward the context to another level.
That code gets compiled to this JS:
var foo;
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
foo = function() {
return this.a = {
getThis: __bind(function() {
return this;
}, this)
};
};
Which basically just does what you say you do not want to do.
Or if the value doesn't have to this specifically, you can set the "owner" in the child object.
var A = function(owner) {
this.owner = owner;
};
A.prototype.getThis = function() {
return this.owner;
};
var Foo = function() {
this.a = new A(this);
};
var foo = new Foo();
if (foo.a.getThis() === foo) {
alert('Happy dance');
} else {
window.location = 'https://commons.lbl.gov/download/attachments/73468687/sadpanda.png';
}
http://jsfiddle.net/4GQPa/
And the coffee script version of that because I am a passionate and unreasonable zealot for it:
class A
constructor: (#owner) ->
getThis: -> #owner
class Foo
constructor: -> #a = new A(this)
foo = new Foo()
if foo.a.getThis() is foo
alert 'Happy Dance'
else
window.location = 'https://commons.lbl.gov/download/attachments/73468687/sadpanda.png'
Impossible to do reliably without binding the value at the start since the value of a function's this is set by the call. You can't know beforehand how it will be called, or which functions need a special or restricted call to "preserve" the this -> this relationship.
The function or caller's this may be any object, there may not be a this -> this at all. Consider:
var x = {
a : {
b: function() {return this;}
}
}
When you call x.a.b(), then b's this is a. But if you do:
var c = x.a.b;
c(); // *this* is the global object
or
x.a.b.call(someOtherObject);
What is the value of this -> this in these cases?
Answering my own question because someone else may find it useful. Not sure if I'll end up going with this or Squeegy's solution. The functions are only ever defined once and then the containing object is cloned and has parent = this injected into it:
function foo(){
var self = this, nest = this.__nestedObjects__ || [];
nest.forEach(function(prop){
self[prop] = extend({ parent : self }, self[prop]);
});
}
// bound like this so that they're immutable
Object.defineProperties(foo.prototype, {
bar : {
enumerable : true,
value : {
foobar : function(){
return this.parent;
},
foo : function(){},
bar : function(){}
}
},
__nestedObjects__ : { value : ['bar'] }
});
var fooInst = new foo();
console.log(fooInst.bar.foobar() == fooInst);
or based on Squeegy's solution:
function foo(){
for(var cls in this.__inherit__){
if(!this.__inherit__.hasOwnProperty(cls)){ continue; }
this[cls] = new (this.__inherit__[cls])(this);
}
}
var clsA;
// bound like this so that they're immutable
Object.defineProperties(foo.prototype, {
__inherit__ : { value : {
bar : clsA = function(parent){
Object.defineProperty(this, '__parent__', { value : parent });
}
}
}
});
clsA.prototype = {
foobar : function(){
return this.__parent__;
}
};
var fooInst = new foo();
console.log(fooInst.bar.foobar() == fooInst);