javascript .prototype for object function extensions - javascript

--
Hello SO,
Hoping for some minor guidance on the issue of .prototype.
I've gone through all the answers in SO and they did not seem to cover this specific question, or maybe they did but I did not understood it like that.
The question at hand (and code)
function foo(){};
foo.prototype.type = 'foo';
function bar()
{
this.prototype = foo.prototype;
}
test = new bar();
console.log(test.type); // type is undefined
The question
From what I understand, the request for the type had to cascade up the prototype chain until it found the foo prototype, This did not happen, Obviously I'm understanding something wrong - Why is type undefined?
I'm basically trying to find a way to extend a function object so that
new foo() - return a foo object
new bar() - return a bar object that has all the methods and properties of foo.
I appreciate any help or reference I can get!

Well, when you do this:
function bar()
{
this.prototype = foo.prototype;
}
you are not changing the bar object prototype but assigning a new property to the bar object called prototype, which has the foo object prototype, basically: { type: 'foo' }.
then:
test = new bar();
console.log(test.type); // type is undefined
of course is undefined! you never define it, you just define the prototype property
console.log(test.prototype); // I have surprises for you
I think you want somethink like inheritance. I suggest the Crockford way of inheritance:
Function.prototype.inherits = function (Parent) {
this.prototype = new Parent();
return this;
};
Then, just do:
bar.inherits(foo);
Now,
test = new bar();
console.log(test.type); // foo!
Hope this helps

Thanks for the comments and replies, to extend lante's answer to what I think is fully explaining the situation.
A JavaScript function is of course an object, When you instantiate a new instance of a function object, The created object receives the prototype of that function.
for instance,
var Foo = fn() {
this.ok= 'this is okay';
}
var Bar = fn(){};
Bar.prototype = new Foo(); // Bar.prototype is now a regular object, nothing fancy.
//for all intents and purposes, this is exactly like doing this :
Bar.prototype = {ok : 'this is okay'}; //just assigns an object, reduntent
var test = new Bar(); //new Bar instance
console.log(test.ok); //prints 'bar'
What's the magic?
test has no ok property, But when it's being called it chains up to the function object's prototype and tries to find it there, if it can't, it keeps moving up until it reaches the end.
Thanks again for all the answers

Related

Why does the __proto__ object evaluate to "Object" in the debugger?

I'm reading Kyle Simpson's "YDKJS: this & Object Prototypes", and looking at his example of behavior delegation. Here's the code below:
Foo = {
init: function(who) {
this.me = who;
},
identify: function() {
return "I am " + this.me;
}
};
Bar = Object.create( Foo );
Bar.speak = function() {
alert( "Hello, " + this.identify() + "." );
};
var b1 = Object.create( Bar );
b1.init( "b1" );
var b2 = Object.create( Bar );
b2.init( "b2" );
b1.speak();
b2.speak();
He uses this diagram to describe the relationships between these objects:
Now my question:
When tinkering with this code in Chrome Developer tools, I see that the __proto__ object evaluates to Object. Why is that? Shouldn't the __proto__ object depict the actual relationship in the diagram, where b1 and b2 delegate to Bar which in-turn delegates to Foo? Why are these relationships not explicitly named in the __proto__ object? After-all, this implementation uses the Object.create() method, and places an argument in the proto parameter (the first parameter). Wouldn't it be expected that the console would return that named argument as the value of the __proto__ object?
This isn't quite so simple. The __proto__ property is a dynamic link to the .constructor's prototype.
However, .constructor isn't overwritten in these cases (though it can be in certain hand-made libraries).
When you're looking for a reference to Foo to show up in that chain, it's a very "classical" viewpoint, and less to do with prototypal inheritance, which inherits from a concrete instance, rather than a class, and in the case of JS, references (when not scalar), rather than copies.
The tl;dr reason is simply: Object.create's constructor is Object, {}'s constructor is Object and Object.prototype's constructor is Object.
The Long Way
First thing to know:
names in these lookups aren't tied to variables, but rather they're tied to functions, typically.
Once upon a time, the field where this information could be found was hidden, and now it's found it's way to the .name property of a function (function Foo () { } Foo.name; //Foo) in many browsers now (much like __proto__ used to be invisible.
Second bit:
names which you see in console references, and in type-checks, aren't based on the proto, but on a property called .constructor.
// Equivalent assignments
var obj1 = { };
var obj2 = new Object();
var obj3 = Object.create(Object.prototype);
obj1.constructor; // Object
obj2.constructor; // Object
obj3.constructor; // Object
If we were to change the dynamic a little, and introduce the more "classical" approach to instance-creation, which is paseé, but will see a resurgence in ES6 with the class sugar...
function Foo () {
this.isFoo = true;
}
var foo = new Foo();
foo.isFoo; // true
foo.constructor; // Foo
foo.__proto__ === Foo.prototype; // true
foo.__proto__.constructor; // Object
That last little bit there is telling, for your immediate question; Foo.prototype is nothing but a plain ol' Object instance.
In the days of JS where everybody was looking for the best possible way of making JS feel like Java / C#, you'd see something like:
function Foo () { }
function Bar() { }
Bar.prototype = new Foo();
var foo = new Foo();
var bar = new Bar();
bar instanceof Bar; // true
bar instanceof Foo; // true
On one hand, this sort of works, as we've been able to reuse method's of Foo on instances of Bar.
Grand.
The immediate downside is that all instances of Bar share the same instance of Foo, including all of its instance-specific properties.
While this method is far from what I'd suggest as a pattern for reuse, it does show off your dilemma well.
// using the last set of assignments
bar instanceof Foo;
// equivalent to:
bar.constructor === Foo; // false
bar.__proto__.constructor === Foo; // true
// not equivalent to
bar.__proto__ == Foo;
More modern forms of "classical" inheritance (calling a super constructor, copying prototypes of other constructors onto your new constructor, etc) do a better job of allowing you to compose and reuse methods...
But that comes at the cost of being able to rely on the __proto__ chain for looking up where those loaned methods come from.
Historically, the "bad for reuse, good for type-checking" model let you search
val.__proto__.__proto__.__proto__.__proto__. (...) .__proto__.constructor
until it matched your instanceof, or until you hit Object at the end of the line.
Newer forms copy the values directly onto val.__proto__ (/ val.constructor.prototype, which we've seen is the same object, at creation of val), which means your proto chain runs out very quickly.

What harm can omitting prototype.constructor cause when inheriting? [duplicate]

Trying to bend by head around Javascript's take on OO...and, like many others, running into confusion about the constructor property. In particular, the significance of the constructor property, as I can't seem to make it have any effect. E.g.:
function Foo(age) {
this.age = age;
}
function Bar() {
Foo.call(this, 42);
this.name = "baz";
}
Bar.prototype = Object.create(Foo.prototype);
var b = new Bar;
alert(b.constructor); // "Foo". That's OK because we inherit `Foo`'s prototype.
alert(b.name); // "baz". Shows that Bar() was called as constructor.
alert(b.age); // "42", inherited from `Foo`.
In the above example, the object b seems to have had the right constructor called (Bar) – and it inherits the age property from Foo. So why do many people suggest this as a necessary step:
Bar.prototype.constructor = Bar;
Clearly, the right Bar constructor was called when constructing b, so what impact does this prototype property have? I am curious to know what practical difference it actually makes to have the constructor property set 'correctly'—as I can't see it having any affect on which constructor is actually called after an object is created.
Step one is to understand what constructor and prototype are all about. It's not difficult, but one has to let go of "inheritance" in the classical sense.
The constructor
The constructor property does not cause any particular effects in your program, except that you can look at it to see which function was used in conjunction with the operator new to create your object. If you typed new Bar() it will be Bar and you typed new Fooit will be Foo.
The prototype
The prototype property is used for lookup in case the object in question does not have the property asked for. If you write x.attr, JavaScript will try to find attr among x's attributes. If it cant find it, it will look in x.__proto__. If it's not there either, it will look in x.__proto__.__proto__ and so on as long as __proto__ is defined.
So what is __proto__and what has it got to do with prototype? Shortly put, prototype is for "types" while __proto__ is for "instances". (I say that with quotation marks because there's not really any difference between types and instances). When you write x = new MyType(), what happens (among other things) is that x.__proto___ is set to MyType.prototype.
The question
Now, the above should be all you need to derive what your own example means, but to try and answer your actual question; "why write something like":
Bar.prototype.constructor = Bar;
I personally have never seen it and I find it a little silly, but in the context you've given it will mean that the Bar.prototype-object (created by using new Foo(42)) will pose as have being created by Bar rather than Foo. I suppose the idea is some make something similar to C++/Java/C#-like languages where a type-lookup (the constructor property) will always yield the most specific type rather than the type of the more generic object further up in the prototype-chain.
My advice: don't think very much about "inheritance" in JavaScript. The concepts of interfaces and mixins makes more sense. And don't check objects for their types. Check for the required properties instead ("if it walks like a duck and quacks like a duck, it's a duck").
Trying to force JavaScript into a classical inheritance model, when all that it has is the prototype-mechanism as described above, is what causes the confusion. The many people that suggested to manually set the constructor-property probably tried to do just that. Abstractions are fine, but this manual assignment of the constructor property is not very idiomatic usage of JavaScript.
September 2020 Update
The answer below is from the days of ECMAScript 3 and the first sentence is no longer true because since ECMAScript 6, the constructor property is used in a few places. However, I think the overall gist still applies. Thanks to T. J. Crowder for pointing that out in the comments, and please read his answer for a fuller picture of the current situation.
Original answer
The constructor property makes absolutely no practical difference to anything internally. It's only any use if your code explicitly uses it. For example, you may decide you need each of your objects to have a reference to the actual constructor function that created it; if so, you'll need to set the constructor property explicitly when you set up inheritance by assigning an object to a constructor function's prototype property, as in your example.
one case to use constructor:
this is one of the common realization of inheritance:
Function.prototype.extend = function(superClass,override) {
var f = new Function();
f.prototype = superClass.prototype;
var p = this.prototype = new f();
p.constructor = this;
this.superclass = superClass.prototype;
...
};
this new f() would not call the constructor of superClass,so when you create a subClass,maybe you need call the superClass at first,like this:
SubClass = function() {
SubClass.superClass.constructor.call(this);
};
so the constructor property make sense here.
The previous answers here say (in various ways) that the value of the constructor property isn't used by anything in JavaScript itself. That was true when those answers were written, but ES2015 and onward have started using constructor for things.
The constructor property of the prototype property of a function is meant to point back to the function so that you can ask an object what constructed it. It's set up automatically as part of creating a traditional function object or a class constructor object (details).
function TraditionalFunction() {
}
console.log(TraditionalFunction.prototype.constructor === TraditionalFunction); // true
class ExampleClass {
}
console.log(ExampleClass.prototype.constructor === ExampleClass); // true
Arrow functions don't have a prototype property, so they don't have prototype.constructor.
For years the JavaScript specification only said that the constructor property would be there and have that value (a link back to the function) by default. But starting in ES2015, that changed, and various operations in the specification now actually use the constructor property, such as this, this, this, and this.
So when setting up constructor functions that build inheritance chains, it's best to ensure that the constructor property is referring to the appropriate function. See my answer here for examples, etc.
One of the use cases when you would want the prototype.constructor property to survive prototype property reassignment is when you define a method on the prototype that produces new instances of the same type as the given instance. Example:
function Car() { }
Car.prototype.orderOneLikeThis = function() { // Clone producing function
return new this.constructor();
}
Car.prototype.advertise = function () {
console.log("I am a generic car.");
}
function BMW() { }
BMW.prototype = Object.create(Car.prototype);
BMW.prototype.constructor = BMW; // Resetting the constructor property
BMW.prototype.advertise = function () {
console.log("I am BMW with lots of uber features.");
}
var x5 = new BMW();
var myNewToy = x5.orderOneLikeThis();
myNewToy.advertise(); // => "I am BMW ..." if `BMW.prototype.constructor = BMW;` is not
// commented; "I am a generic car." otherwise.
The constructor property points to the constructor that was used to create the object instance. If you typed 'new Bar()' it will be 'Bar' and you typed 'new Foo()' it will be 'Foo'.
But if you set the prototype without setting the constructor, you would get something like this:
function Foo(age) {
this.age = age;
}
function Bar() {
this.name = "baz";
}
Bar.prototype = new Foo(42);
var one = new Bar();
console.log(one.constructor); // 'Foo'
var two = new Foo();
console.log(two.constructor); // 'Foo'
To set the constructor actually to the constructor that was used to create the object, we need to set the constructor as well while setting prototype as follows:
function Foo(age) {
this.age = age;
}
function Bar() {
this.name = "baz";
}
Bar.prototype = new Foo(42);
Bar.prototype.constructor = Bar;
var one = new Bar();
console.log(one.constructor); // 'Bar'
var two = new Foo();
console.log(two.constructor); // 'Foo'

Javascript: Generating a self executing class that is callable and extendable in window context

some beginner question here but i can't seem to find a working answer for my problem. I want to write a self executing, global javascript class 'foo' whose methods can be called from window context (like window.foo.bar() or just foo.bar() in javascript console), without having to instantiate the class.
At the same time, i want to be able to extend said class with custom functions, e.g.
foo.fn.baz = function() {}
This is how far i have gotten this far:
(function (window) {
var foo = function() {
return this;
};
foo.fn = foo.prototype = {
bar: function (string) {
console.log(string);
}
};
window.foo = foo;
})(window);
When i execute this javascript, the js console now knows the class foo, and i can extend its functions via foo.fn.baz = function(){} but i can't call those functions: foo.bar is undefined.
If i change the code from window.foo = foo; to window.foo = new foo();, then i can call the functions, but i can't extend the class anymore.
How do i do this rigt? Is my code anywhere near the right way to do such a thing? Is it even possible to get both things at the same time?
Anyone with an idea or a hint? Anything would be great.
thanks
foo.bar is undefined
Right. You've put the methods on the prototype property of the function. The object that foo.prototype refers to will get assigned to instances you create via the new operator, as their underlying prototype. So:
var f = new foo();
f.bar();
If you want a singleton (foo is, itself, the one object and you can call foo.bar()), you don't need prototypes at all:
window.foo = {
bar: function(string) {
console.log(string);
}
};
...but as you used the word "class," my guess is that you really do want to create multiple instances using foo, rather than using foo directly, so new foo() would be what you want.
Side note: The overwhelming convention in JavaScript is that if a function is expected to be called via new, it starts with an upper-case letter. So Foo rather than foo.

Javascript and Inheritance

Say I have a Class:
function Foo() {
this.foo1 = null;
this.foo2 = function() { return false;};
}
And I want other objects to inherit variables & functions from it.
function Bar(){}
function Baz(){}
Then instantiate my objects:
var bar = new Bar();
bar.foo1 // returns null
bar.foo2() // returns false
What's the proper function to include Foo in Bar and Baz?
I already did Bar.prototype = new Foo(); but it seems to fail on our beloved IE (<9).
If you attach all the properties to the prototype (which is preferable, at least for methods),
function Foo() {}
Foo.prototype.foo1 = null;
Foo.prototype.foo2 = function() { return false;};
then assigning the parent's prototype to the child's prototype is sufficient:
function inherit(Child, Parent) {
var Tmp = function(){};
Tmp.prototype = Parent.prototype;
Child.prototype = new Tmp();
Child.prototype.constructor = Child;
}
inherit(Bar, Foo);
Here we used an intermediate constructor function to "decouple" the two prototypes. Otherwise if you'd change one, you'd change the other one too (as they reference the same object). This way is actually pretty popular and used by a couple of libraries.
If not, you have to call the parent's constructor function inside the child's constructor function:
function Bar() {
Foo.call(this);
}
This is something you always should do, to assign the properties set up in the constructor function to the current object.
An additional remark to your way:
Bar.prototype = new Foo();
this should work (also in IE actually), but it has two major flaws:
All the instance properties set up in Foo will become properties shared by all Bar instances.
What if Foo expects some arguments that are only available when you create a Bar instance?
have a look to Classy or, if you like Ruby and want a more complete solution to JS.Class. Those libraries helps you with object orientation in javascript ad hide prototype to the developer.
Hope this helps

What is the significance of the Javascript constructor property?

Trying to bend by head around Javascript's take on OO...and, like many others, running into confusion about the constructor property. In particular, the significance of the constructor property, as I can't seem to make it have any effect. E.g.:
function Foo(age) {
this.age = age;
}
function Bar() {
Foo.call(this, 42);
this.name = "baz";
}
Bar.prototype = Object.create(Foo.prototype);
var b = new Bar;
alert(b.constructor); // "Foo". That's OK because we inherit `Foo`'s prototype.
alert(b.name); // "baz". Shows that Bar() was called as constructor.
alert(b.age); // "42", inherited from `Foo`.
In the above example, the object b seems to have had the right constructor called (Bar) – and it inherits the age property from Foo. So why do many people suggest this as a necessary step:
Bar.prototype.constructor = Bar;
Clearly, the right Bar constructor was called when constructing b, so what impact does this prototype property have? I am curious to know what practical difference it actually makes to have the constructor property set 'correctly'—as I can't see it having any affect on which constructor is actually called after an object is created.
Step one is to understand what constructor and prototype are all about. It's not difficult, but one has to let go of "inheritance" in the classical sense.
The constructor
The constructor property does not cause any particular effects in your program, except that you can look at it to see which function was used in conjunction with the operator new to create your object. If you typed new Bar() it will be Bar and you typed new Fooit will be Foo.
The prototype
The prototype property is used for lookup in case the object in question does not have the property asked for. If you write x.attr, JavaScript will try to find attr among x's attributes. If it cant find it, it will look in x.__proto__. If it's not there either, it will look in x.__proto__.__proto__ and so on as long as __proto__ is defined.
So what is __proto__and what has it got to do with prototype? Shortly put, prototype is for "types" while __proto__ is for "instances". (I say that with quotation marks because there's not really any difference between types and instances). When you write x = new MyType(), what happens (among other things) is that x.__proto___ is set to MyType.prototype.
The question
Now, the above should be all you need to derive what your own example means, but to try and answer your actual question; "why write something like":
Bar.prototype.constructor = Bar;
I personally have never seen it and I find it a little silly, but in the context you've given it will mean that the Bar.prototype-object (created by using new Foo(42)) will pose as have being created by Bar rather than Foo. I suppose the idea is some make something similar to C++/Java/C#-like languages where a type-lookup (the constructor property) will always yield the most specific type rather than the type of the more generic object further up in the prototype-chain.
My advice: don't think very much about "inheritance" in JavaScript. The concepts of interfaces and mixins makes more sense. And don't check objects for their types. Check for the required properties instead ("if it walks like a duck and quacks like a duck, it's a duck").
Trying to force JavaScript into a classical inheritance model, when all that it has is the prototype-mechanism as described above, is what causes the confusion. The many people that suggested to manually set the constructor-property probably tried to do just that. Abstractions are fine, but this manual assignment of the constructor property is not very idiomatic usage of JavaScript.
September 2020 Update
The answer below is from the days of ECMAScript 3 and the first sentence is no longer true because since ECMAScript 6, the constructor property is used in a few places. However, I think the overall gist still applies. Thanks to T. J. Crowder for pointing that out in the comments, and please read his answer for a fuller picture of the current situation.
Original answer
The constructor property makes absolutely no practical difference to anything internally. It's only any use if your code explicitly uses it. For example, you may decide you need each of your objects to have a reference to the actual constructor function that created it; if so, you'll need to set the constructor property explicitly when you set up inheritance by assigning an object to a constructor function's prototype property, as in your example.
one case to use constructor:
this is one of the common realization of inheritance:
Function.prototype.extend = function(superClass,override) {
var f = new Function();
f.prototype = superClass.prototype;
var p = this.prototype = new f();
p.constructor = this;
this.superclass = superClass.prototype;
...
};
this new f() would not call the constructor of superClass,so when you create a subClass,maybe you need call the superClass at first,like this:
SubClass = function() {
SubClass.superClass.constructor.call(this);
};
so the constructor property make sense here.
The previous answers here say (in various ways) that the value of the constructor property isn't used by anything in JavaScript itself. That was true when those answers were written, but ES2015 and onward have started using constructor for things.
The constructor property of the prototype property of a function is meant to point back to the function so that you can ask an object what constructed it. It's set up automatically as part of creating a traditional function object or a class constructor object (details).
function TraditionalFunction() {
}
console.log(TraditionalFunction.prototype.constructor === TraditionalFunction); // true
class ExampleClass {
}
console.log(ExampleClass.prototype.constructor === ExampleClass); // true
Arrow functions don't have a prototype property, so they don't have prototype.constructor.
For years the JavaScript specification only said that the constructor property would be there and have that value (a link back to the function) by default. But starting in ES2015, that changed, and various operations in the specification now actually use the constructor property, such as this, this, this, and this.
So when setting up constructor functions that build inheritance chains, it's best to ensure that the constructor property is referring to the appropriate function. See my answer here for examples, etc.
One of the use cases when you would want the prototype.constructor property to survive prototype property reassignment is when you define a method on the prototype that produces new instances of the same type as the given instance. Example:
function Car() { }
Car.prototype.orderOneLikeThis = function() { // Clone producing function
return new this.constructor();
}
Car.prototype.advertise = function () {
console.log("I am a generic car.");
}
function BMW() { }
BMW.prototype = Object.create(Car.prototype);
BMW.prototype.constructor = BMW; // Resetting the constructor property
BMW.prototype.advertise = function () {
console.log("I am BMW with lots of uber features.");
}
var x5 = new BMW();
var myNewToy = x5.orderOneLikeThis();
myNewToy.advertise(); // => "I am BMW ..." if `BMW.prototype.constructor = BMW;` is not
// commented; "I am a generic car." otherwise.
The constructor property points to the constructor that was used to create the object instance. If you typed 'new Bar()' it will be 'Bar' and you typed 'new Foo()' it will be 'Foo'.
But if you set the prototype without setting the constructor, you would get something like this:
function Foo(age) {
this.age = age;
}
function Bar() {
this.name = "baz";
}
Bar.prototype = new Foo(42);
var one = new Bar();
console.log(one.constructor); // 'Foo'
var two = new Foo();
console.log(two.constructor); // 'Foo'
To set the constructor actually to the constructor that was used to create the object, we need to set the constructor as well while setting prototype as follows:
function Foo(age) {
this.age = age;
}
function Bar() {
this.name = "baz";
}
Bar.prototype = new Foo(42);
Bar.prototype.constructor = Bar;
var one = new Bar();
console.log(one.constructor); // 'Bar'
var two = new Foo();
console.log(two.constructor); // 'Foo'

Categories

Resources