Javascript module pattern - Object.create - javascript

A bit of confusion regarding what exactly is going on here.
given this simple code :
stuff = (function(){
function extendFoo(bar)
{
$.extend(this.foo,bar);
}
this.foo = {};
return { foo : foo, extendFoo: extendFoo};
})();
Following this simple operation :
zz = Object.create(stuff);
zz.extendFoo({bar:'bar'});
vv = Object.create(stuff); //foo is still extended(??)
So from what I realized, operations conducted on the returned object form Object.create still affect the prototype of that Object, So when you create a new object, his prototype is changed, thus resulting in a 'modified' version.
This seems wrong on a lot of levels, Can anyone explain what's going on here?
this behavior is not reproducible using the following pattern :
stuff = (function(){
function setFoo(bar)
{
this.foo = bar;
}
var foo;
return { foo : foo, setFoo: setFoo};
})();
So I suspect $.extend is to blame here.
Any input would be great!

This problem has nothing to do with the module pattern and everything to do with prototypes.
zz = Object.create(stuff)
creates a new object with stuff as its prototype.
vv = Object.create(stuff)
creates a new object with the same stuff object as its prototype.
Both zz and vv share the same prototype object, so if you modify the prototype object stuff, then changes will reflect in both derived objects zz and vv. It doesn't matter whether you're modifying the prototype via $.extend or other means, and it doesn't matter whether you're modifying the prototype via your derived object or your prototype.
In your code, the foo object is attached to the prototype, not to the derived objects zz and vv. When extendFoo is invoked on the derived object zz, it is modifying foo on the prototype, so changes to foo are shared by the derived objects.
In your second example, in setFoo
this.foo = bar;
what's happening is that you're setting the foo property on the derived object so now it overrides the prototype's foo. After you run setFoo on a derived object, that object's foo is no longer the prototype's foo. You can see this by running
zz = Object.create(stuff);
console.log(zz.hasOwnProperty('foo')); // false
zz.setFoo(bar);
console.log(zz.hasOwnProperty('foo')); // true
delete zz.foo;
console.print(zz.foo); // foo is the original foo, not null
console.log(zz.hasOwnProperty('foo')); // false
you'd actually get back your original foo instead of null.
The reason why setFoo works in the second case is because you are no longer modifying the prototype, so the changes are no longer shared between derived objects. With the original's
$.extend(this.foo,bar);
you're modifying the object this.foo in place and not overriding. You can also see this via hasOwnProperty
zz = Object.create(stuff);
console.log(zz.hasOwnProperty('foo')); // false
zz.extendFoo({bar:'bar'});
console.log(zz.hasOwnProperty('foo')); // false

Related

Function object prototype [duplicate]

This question already has answers here:
How does JavaScript .prototype work?
(26 answers)
Closed 7 years ago.
function funcObj() { }
funcObj.prototype.greet = "hello";
console.log(funcObj.greet) // undefined ???
console.log(funcObj.prototype.greet) // hello
var obj = new funcObj();
console.log(obj.greet); // hello
As per my understanding in prototype. If you access a member of an object it will get it from prototype object when not available in that object.
My questions is:
since functions in Javascript are objects why funcObj.greet -> undefined, but obj.greet -> hello?
A prototype is nothing more than an object from which instances inherit properties.
So, funcObj is an instance of another prototype (the one of Function) from which it has inherited all the properties. Also, it has for itself a prototype on which you can bind whatever you want and that prototype will be used once you invoke it to construct new instances of funcObj (that is, when you invoke it along with the new keywork, as new funcObj()).
Because of that, it's perfectly normal that funcObj doesn't have a member called greet, while its instances have it.
Because the function is a different object than the instance.
Putting a property on one object will not affect any other object; not even the function that that object or prototype is an instance of.
Much like a class Foo is not itself the same type as a new Foo, there is no reason for Foo to have any properties you assign to Foo.prototype. The reasons are a little different, but consider it in another language like java and it's apparent that what you're trying to do just should not work:
class Foo {
public String bar = "analogous to Foo.prototype.bar which is a property of Foo instances";
}
class Baz {
String thisMethodShouldAndWillFail() {
return Foo.bar;
}
String thisIsWhatShouldAndWillWork() {
return (new Foo()).bar;
}
}
In javascript, you need to correct your idea of what a prototype is and how it is related to objects and constructors, or you will run into problems continually. A foo has a prototype, but that prototype is not foo.prototype. There is no property of foo itself that is its prototype. The foo's prototype is determined by its constructor Foo; it makes more sense this way because you could assign any old value to foo.prototype after it is constructed, which breaks foo by turning it into an instance of a class for which it was not initialized.
The constructor Foo would similarly not make any sense if it would act as an instance of the class it defines; it has not been initalized by itself, so it cannot safely be assumed that it will fulfill the behavior intended for its instances. Foo is an instance of Function, which makes sense because it can be called. Therefore the prototype of Foo is Function.prototype, not Foo.prototype.
The relationship between a foo and its prototype is set up when you call foo = new Foo. Since the body of the constructor Foo is expected to initialize the instance, this is the only time to give foo its prototype that makes sense. The prototype provides an object its common behaviors, the constructor initializes the object so that these behaviors will work as intended. The prototype that is assigned to foo when it is constructed via new Foo is none other than Foo.prototype; this is done before Foo is executed for convenience and a guarantee that it cannot possibly be messed up. Following that, there is no way to access the prototype of foo without going through Foo explicitly.
enter code here

Is this a subclass or new instance?

I know JavaScript inheritence is much different than typical OO languages (Java, c++, etc.). Searching around, there also seems to be many different ways to create classes and class hierarchies. Because of this I'm confused about JavaScript inheritence.
Given the following code
if (!com) var com = {};
if (!com.foobar) com.foobar = {};
com.foobar.Foo = {
foo : "foo",
bar : "bar",
baz : function () {
return true;
}
};
Why is the following not allowed? Why is com.foobar.Foo not a constructor? Is it because Foo is not a function, but an object?
var baz = new com.foobar.Foo();
Since I cannot do the above, how would I create a new Foo?
If I want to extend Foo, I thought I would do this:
var bar = Object.create(com.foobar.Foo, {buz: {value: "neat"}});
.. but is bar a subtype of Foo or an instance of Foo? I'm leaning towards instance of Foo because the following prints 'undefine'
console.log(bar.prototype);
You're correct, you can't do var baz = new com.foobar.Foo(); because Foo is an object, not a function.
Object.create is used to set the prototype of a variable (i.e. bar.prototype = Object.create(/*etc etc*/)). For more information, see the MDN page: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create
Using Object.create properly results in bar being another object with the prototype of Foo. This means that anything Foo has can be used on bar, eg bar.bar === 'bar' (if that makes sense). Changes to Foo will be reflected in bar, but not the other way around. It's not quite a subtype. (JS is weird, but it's delightfully so.)
For more on this, check out MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript
Javascript has no classes, only objects. When you create an object, it can also have a prototype, which is just another object that the created object will use to delegate calls to properties (or functions) it doesn't itself understand.
This works more or less like classic inheritance, since subclasses also delegate calls it doesn't understand to superclasses.
So, taking that lead, you'd like to make Foo a prototype for other objects you create; Foo would act somewhat like a superclass to the objects.
A handy function you already know about is the Object.create. You can use it to create a new object with a specific prototype, as you did:
var bar = Object.create(com.foobar.Foo, {buz: {value: "neat"}});
This means that bar will have a prototype of Foo and also will have an own property (i.e. not in the prototype) of buz.
Now, the prototype of bar, which points to Foo, can be found (at least in Chrome, since this is implementation specific) on the property __proto__. So this is true: bar.__proto__ === com.foobar.Foo.
Moving forward, if you want bar to also be a superclass prototype of another object, you'd do the same:
var subbar = Object.create(bar);
Makes sense? I'll later add more about Function, the property prototype and the new operator if you want....
You are not able to instantiate Foo because it is an object, not a function. You can accomplish that by creating a function and using prototype to set the instance methods:
// constructor method
com.foobar.Foo = function() {
this.foo = 'foo'
this.bar = 'bar'
}
com.foobar.Foo.prototype.baz = function() {
return true
}
Take a look at it running on jsfiddle: http://jsfiddle.net/DE7KZ/

how to make use of prototypal inheritance in js [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I'm getting stuck because of less understanding of prototypal inheritance. I want to know what is prototypal inheritance exactly and how it is implemented.
Could you please show one ease example?
Any help is appreciated.
At its core
Imagine you have an object and you want to look up a property. Now imagine the property doesn't exist. What if you could make it automatically continue the search for that property on a different object? That's basically what prototypal inheritance is.
How do we do it?
So then the only question is how to create this relationship between objects. Well, that's the weird part.
I'll start with the main, historical way of doing it. That is using functions.
First thing to note is that a function in JavaScript is itself an object. It can have its own properties, and it uses prototypal inheritance to gain access to other properties.
So let's start by creating a function.
function Foo() {
// our function
}
So now we have a function named Foo. Our new function automatically gets a property named prototype when it's created. That property references an (almost) empty object.
console.log(typeof Foo.prototype); // object
Why does that property and object exist? Well, they exist to support the weird way that JavaScript has formed that relationship between objects that I described above.
Basically, the Foo.prototype object is what we're going to use as the "backup" object when looking for new properties on our objects. But we still haven't formed any special relationship between the object we want to use, and the Foo.prototype object.
Putting it to work
To do that, we actually invoke the function using the new operator.
var my_object = new Foo();
And there we go. So now my_object is a new, empty object. But it has in its "prototype chain" that object that is dangling from our Foo function off of its .prototype property. In other words, when we look for a property on my_object, if the property doesn't exist, it'll continue the search on the Foo.prototype object.
See it in action
Trouble is that we haven't added anything that we might find useful to Foo.prototype. But there actually is one property on that object. That property was also automatically created when we made our Foo function, and it's the .constructor property.
What does that property reference? It has a reference back to the Foo function. In other words:
Foo.prototype.constructor === Foo; // true
Alright, so if our my_object is empty, and if when looking for a property on my_object that doesn't exist, it continues the search on the Foo.prototype object, then that should mean that we should be able to automatically get to the Foo.prototype.constructor property from my_object.
my_object.constructor === Foo; // true
And it works. Since my_object didn't have a property named constructor, it continued its search on the object from which it inherits, which is Foo.prototype, which as we know, has a .constructor property that refers to the Foo function.
Customizing for our code
Super. But how do we set up other properties that are more useful to us in our code? We just add them to Foo.prototype. That will let our my_object find those properties if the object doesn't own them directly.
// give a custom property to `Foo.prototype`
Foo.prototype.bar = "foobar";
// see if we can access that property on your object
my_object.bar === "foobar"; // true
Sure enough, it worked. So let's see if we can create a new object from Foo that also has access to that .bar property.
var another_object = new Foo();
another_object.bar === "foobar"; // true
Again, it works. This is because all objects created by invoking Foo using the new keyword will have in their prototype chain the Foo.prototype object. In other words, Foo.prototype is shared among all instances created from Foo.
So if we now modify the Foo.prototype.bar property, it will be reflected in both objects we created.
Foo.prototype.bar = "raboof";
my_object.bar === "raboof"; // true
another_object.bar === "raboof"; // true
So we can see that both of our objects are simply looking for properties that they don't have by passing the search on to the next object in their "prototype chain", which is that weird object dangling off the Foo function... Foo.prototype.
There's more to learn
There are newer ways to set up this object relationship, but this is the original way, and in spite of its weirdness, should probably be understood first.
This is how I understand it:
This could be considered a constructor
var Thing = function(){
this.method1 = function(){
alert( "method 1" );
}
}
This is an instance of it
var a_thing = new Thing();
a_thing.method1();
Now, if you add something to the prototype of the constructor, it is automatically available to the already instantiated object.
Thing.prototype.method2 = function(){
alert( "method2" );
}
a_thing.method2();
Hope this helps.
This is the simplest example I can think of,
pizza class inherits from circle by using this line:
pizza.prototype = new circle();
Full example:
<html>
<head>
<script>
// base class
function circle(radius){
this.radius = radius;
this.getArea = function ()
{
return (this.radius * this.radius) * Math.PI;
};
this.foo = function ()
{
return "circle foo";
};
return true;
}
// child class
function pizza(flavour, radius){
circle.call(this, radius);
this.flavour = flavour;
this.foo = function ()
{
return "pizza foo";
};
return true;
}
// Inheritance
pizza.prototype = new circle();
function Go(){
// Instancing new object
var myCircle = new circle(8);
var myPizza = new pizza("Onion", 5);
// Calling property
var pizza_area = myPizza.getArea();
// Calling override foo function
var foo = myPizza.foo();
// Calling foo base class
var base = pizza.prototype.foo.call(myPizza);
//Line.prototype.someFunction.call(myLine);
var isBase = myCircle instanceof pizza;
isBase = myPizza instanceof pizza;
}
</script>
</head>
<body onload="Go();">
</body>
</html>

How to show the delegated `constructor` reference issue in javascript?

In the example below I noticed the comment "fixes the delegated constructor reference" and I'm curious -how can I show this "not working / then working after I add that line of javascript?
full gist here => https://gist.github.com/getify/5572383
Thank you in advance
function Foo(who) {
this.me = who;
}
Foo.prototype.identify = function() {
return "I am " + this.me;
};
function Bar(who) {
Foo.call(this,"Bar:" + who);
}
Bar.prototype = Object.create(Foo.prototype);
Bar.prototype.constructor = Bar; // "fixes" the delegated `constructor` reference
Functions in javascript are actually objects. When we create any function Foo in Javascript, the interpreter automatically creates a prototype property Foo.prototype, which is itself an object. The interpreter then creates a constructor property on this object which refers to Foo itself:
console.log(Foo.prototype.constructor); // reference to Foo;
console.log(Foo.prototype.hasOwnProperty("constructor")); // TRUE;
This same process takes place when we create the Bar function. But later we introduce a difference. The difference is that we manually overwrite the object at Bar.prototype with this code:
Bar.prototype = Object.create(Foo.prototype);
Now Bar.prototype has a new object that we created manually. This new object does not have a constructor property because it was created by us and not the interpreter:
console.log(Bar.prototype.hasOwnProperty("constructor")); // FALSE
So Bar.prototype does not have its own constructor property but Foo.prototype does. Next, imagine that we create an instance of Bar:
var myBar = new Bar();
myBar.constructor is an inherited property that does not exist on the myBar object. If we try to access it, the javascript interpreter searches up the prototype chain for the constructor property. It does not find one on Bar.prototype because we overwrote that object. The interpreter continues searching and eventually finds the property on Foo.prototype. As a result, any reference to myBar.constructor will refer to Foo.prototype.constructor, which contains a reference to Foo:
console.log(myBar.constructor); // reference to Foo
So this is why we explicitly set Bar.prototype.constructor manually, so that when traversing the prototype chain, the interpreter will find a constructor property on Bar.prototype as it would have if we hadn't overwritten it:
Bar.prototype.constructor = Bar;
The end result is more useful behavior on our objects:
var myBar2 = new Bar();
console.log(myBar2.constructor); // reference to Bar
This issue should not come up often as it is somewhat rare that one would need to check the constructor property of an object.

improve javascript prototypal inheritance

I'm using a classical javascript prototypal inheritance, like this:
function Foo() {}
Naknek.prototype = {
//Do something
};
var Foo = window.Foo = new Foo();
I want to know how I can improve this and why I can't use this model:
var Foo = window.Foo = new function() {
};
Foo.prototype = {
//Do something
};
Why this code doesn't work? In my head this is more logical than the classical prototypal inheritance.
Your var Foo = window.Foo = new Foo(); example is...odd. First you declare a function Foo, then you assign something to its prototype (I assume you meant to replace Nannak with Foo in your second line), and then you overwrite the reference to the function by assigning to it.
Standard Javascript prototypical inheritance looks like this:
// Create a constructor `Foo`
function Foo() {
}
// Give the prototype for `Foo` objects a function bound to the
// property `bar`
Foo.prototype.bar = function() {
}
// Only do this bit if you're doing this within a function and you want
// to make `Foo` available as a property of `window` (e.g., effectively
// a global variable. If this code is already at global scope, there's
// no need to do this.
window.Foo = Foo;
Here's how you'd use Foo:
// Create a `Foo` and use its `bar`
var f = new Foo();
f.bar();
A couple of other notes:
Never use new function() { ... } unless you really, really know what you're doing. It creates an object initialized by the function, it does not create a new function. There's almost never any need for the similar (but totally different) new Function(...), either, again except for some advanced edge cases.
The function bound to bar in my example above is anonymous (the property it's bound to has a name, but the function does not). I'm not a fan of anonymous functions, but I didn't want to clutter the example above. More here.
If you use var at global scope (it wasn't clear from your question whether you were), it creates a property on the window object. You'd only need to do var Foo = window.Foo = ... if you're within a function and want to both create a propety of window and create a local variable called Foo. (Which maybe you meant to do! :-) )
The Foo.prototype = { .. }; way of assigning prototypical properties works, but it's not generally a good idea (again, unless you're pretty up-to-speed on this stuff). When you do that, you're completely replacing the prototype object used when you call the function via new, whereas if you just add properties to it (Foo.prototype.bar = ...), you're just augmenting the prototype, not replacing it. Replacing the prototype is perfectly valid, but there are some non-obvious things that can happen if you're unwary. :-)
You are using the new operator on the function expression, that causes a newly created object to be assigned to window.Foo.
That new object is not a function, therefore it doesn't have a prototype property and it cannot be invoked.
"doesn't work" is vague, but I think the root cause is new function() { (new doesn't belong here)
You probably want:
var Foo = window.Foo = function() {
};
Foo.prototype = {
bar: 'baz'
};
alert(new Foo().bar); // baz

Categories