Function object prototype [duplicate] - javascript

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

Related

Confused on Prototype inheritance Javascript

I found this picture here
In this case, foo is a constructor function and B and C are objects. I am very confused, first off when you create an object does it always come with the properties and proto? Is that the default? Also in terms of the constructor function for foo. Am I correct to say that every proto of a function defaults to Function.prototype, which uses Object.prototype to create an object? The part that is confusing for me is Foo.prototype, when was this prototype created? Does a constructor function always default to the creation of a prototype which a constructor reference set back to itself and a proto set to object?
No wonder there is confusion. The picture is misleading to the point of being incorrect!
Objects created by calling a constructor function with the new keyword have their inheritance chain set to start with the prototype property of the constructor (correct in the picture).
The prototype property is created every time a function is declared using the function keyword to cover the case of the function being use as a constructor later - so you don't need to specify if a function is a constructor or not. For completeness, functions generated by the class keyword also have a prototype property.)
The function's prototype property's constructor property is set to the function when the prototype property is created (meaning when the function is declared). Again the picture is correct: the value of Foo.prototype.constructor is a reference to Foo.
What is wrong in the picture is objects a and b somehow joining together in a reverse fork and their properties becoming available to instances of Foo.
constructor is always an inherited property. If you replace the original prototype property of a function object with another object, you replace the constructor property inherited by objects constructed with the function. Although you can reset the constructor property of a functions prototype property, it's reasonably unusual and not a part of the story the picture is presenting.
If you do modify the inheritance chain by changing a function's prototype property value, the inheritance chain is still always a single threaded chain back to Object.prototype and then null. The inheritance chain never forks as shown in the picture. If you modified Foo.prototype in the picture to make it a or b, the constructor property of Foo instances would not be Foo.
The picture requires a lot of explanation to be useful.
The properties are assigned in the construction function. Any function can be used with new,thus becoming the "construction function".
var f = function(){};
var fInstance = new f();
console.log(fInstance.constructor); // *f*
If there are no properties assigned in that function (using this.propertyName), then the constructed instance will not have properties. If it does, then it will.
// No properties
var f = function(){};
// Two constructor properties, and one default property
var f = function(prop1, prop2){
this.name = prop1;
this.description = prop2;
this.something = "default";
};
If the prototype of the construction function has properties or methods (basically just glorified properties) attached to its prototype, then each instance will have those.
// No prototype
var f = function(){};
// Prototype with one method
var f = function(){};
f.prototype.test = function(){ console.log("hello"); };
The prototypes and properties must be manually created, and may or may not exist. By default, since using new requires a function, there will always be a constructor function. The process of instantiation using new will also always assign the prototype of the constructor to an object containing the constructing function as a property named constructor as well as all of the properties/methods of the construction function's prototype.
In this case, foo is a constructor function and B and C are objects.
Functions are also objects. Everything are objects. unlike classical inheritance where what defined objects are separate entities. Here an object that is an instance of Function is the constructor that will create an instance of its kind that inherits whatever object is on the constructors prototype attribute.
I am very confused, first off when you create an object does it
always come with the properties and proto? Is that the default?
Only way to get the objects own property y is if the constructor function sets this.y. If a property is not found on the object the system will continue to look at the object that was on the constructors prototype field. Some implementations has this as __proto__ but that is not a requirement. It is implementation specific how it is stored on the instance.
Also in terms of the constructor function for foo. Am I correct to say
that every proto of a function defaults to Function.prototype, which
uses Object.prototype to create an object?
function() {...} makes an instance of the constructor Function. All objects except Object itself inherits Object either indirectly or directly, including Function. Basically you can make a function like this:
var f = new Function('a', 'b', 'return a + b');
f is an instance of Function, as you can see. This is almost the same as:
var f = function(a, b) { return a + b; };
Now the first allows for text to be interpreted as code so its less efficient, but I imagine that in the early days these two would be identical in terms of interpretation. Modern engines prefer the last one since it is more predictable while the first can be seen as a specialized eval.
The part that is confusing for me is Foo.prototype, when was this
prototype created? Does a constructor function always default to the
creation of a prototype which a constructor reference set back to
itself and a proto set to object?
Yes. When the function Foo is created, JS creates by default protoype as new Object(), then it sets constructor to itself. The rest needs to be done in the code itself so we know there is something like this after the actual function code to do the rest of the class:
Foo.prototype.x = 10;
Foo.prototype.calculate = function(...) {...};

Why do functions respond to .prototype but regular objects do not?

Consider:
function Foo() {}
var x = new Foo();
now x and Foo have the same prototype, but only Foo responds to .prototype:
Object.getPrototype(x) === Foo.prototype // true
x.prototype === Foo.prototype // false
Foo.prototype // Foo {} (depending on which browser)
x.prototype // undefined
Why doesn't x.prototype work, but Foo.prototype does work?
prototype is a property of constructors that determines what the prototype of new objects created by that constructor will be. It's only useful to have such a property on a constructor.
As long as the prototype on the constructor hasn't been changed:
Object.getPrototypeOf( x ) === Foo.prototype
and that is the same as:
Object.getPrototypeOf( x ) === x.constructor.prototype
Note that generally:
Object.getPrototypeOf( Foo ) != Foo.prototype
Long story short: functions meant for new have prototype, object instances don't.
I'll probably fail in my precision in saying this, but the prototype is something that only applies to what you might call constructor functions, which are functions meant to be called with new to create instances. The prototype can be thought of as the template for the resulting instance.
For the resulting object, prototype is not a property. Rather, the properties in the constructor's prototype are available as properties on the instance that was created. Meaning that when you look up a property on the instance, if it's not defined on the instance, Javascript will begin checking the prototype chain to see if it's defined there.
If you want to access the prototype of an instance, use Object.getPrototypeOf.
The semantics of Javascript can be confusing. I highly recommend working through the free-to-read Javascript Allongé as a way to thoroughly understand some of Javascript's finer points. Chapter 8 focuses on exactly this topic.

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/

What is the default prototype for a new instance?

I don't understand the following behavior:
var Foo = function () {};
var Bar = function () {};
Foo.prototype = Bar;
var foo = new Foo();
console.log(foo.prototype === Bar.prototype); // true, but why?
I can't find anything in the spec regarding the default value of the prototype property on an object created using a constructor. (I did find this part of the spec which mentions that, for functions, the prototype property defaults to new Object(), but no mention of objects created using constructors.)
So, my question is really two-fold:
What is the default value of the prototype property on an object created using a constructor? (It seems like it is the prototype property of the prototype property of the constructor; e.g. Foo.prototype.prototype)
Where does it explain this behavior in the spec?
What is the default value of the prototype property on an object created using a constructor?
undefined, unless what you're constructing is a function. The prototype property belongs on functions. If an instance object does not have a function object in its prortype chain (i.e., instanceObj instanceof Function is false), the instance generally will not have a prototype property.
The reason that functions have a prototype property because any function might someday be used as a constructor. A constructor's prototype property determines the [[Prototype]] internal property of its constructed instances.
(It seems like it is the prototype property of the prototype property of the constructor; e.g. Foo.prototype.prototype)
You only see with behavior because you've assigned Foo.prototype to the function Bar. Thus, when you try to get foo.prototype, the interpreter looks up foo's prototype chain and finds the prototype property on the function Bar.
In particular, foo.prototype === Bar.prototype is true because:
To get foo.prototype, we first try to get prototype off of foo.
foo has no prototype property.
Look up the prototype chain: foo's [[Prototype]] was set to Foo.prototype when foo was constructed. (Remember, Foo.prototype is the function Bar.)
Look for prototype on Bar.
Success! Bar.prototype is defined. Use that for foo.prototype.
Unsurprisingly, Bar.prototype is equal to Bar.prototype.
Where does it explain this behavior in the spec?
15.3.5.2 explains that the prototype property is used as the [[Prototype]] internal property of its constructed objects.
13.2.2 (steps 5 - 7) spells out the exact procedure described in 15.3.5.2, above.
8.6.2 describes general prototype-based inheritance (i.e., if an object doesn't have a property, look at its [[Prototype]], etc.)
The prototype of a constructed object is the object referenced by the constructor function's .prototype property.
So because foo.__proto__ === Bar, then obviously foo.__proto__.prototype = Bar.prototype.
The foo object does not have .prototype property, it is looked and found in foo.__proto__ because the object's prototype is a function object which have a prototype property, this is what you missed.

What does "the prototype belongs to the class not the instance" mean in javascript?

I asked the question:
Why cant I declare a constructor instantiate an object and then access the prototype?
And you can see that I have marked the answer. I understand the response but Im a bit confused as to what he means by:
The prototype belongs to the class, not the instance:
Does this mean that javascript has a class in this example? I thought javascript was classless? It only has function constructors... At what point does a function constructor become a class? Is it when you add other members to it using the .prototype accessor?
Actually class is an OOP term, not really javascript. What is meant is that the prototype belongs to the constructor. So in
function MyConstructor(prop){
this.foo = prop || 'foo';
}
MyConstructor.prototype.bar = 'allways bar';
var mc1 = new MyConstructor('I am mc1'),
mc2 = new MyConstructor('I am mc2');
alert(mc1.bar) ; //=> allways bar
alert(mc2.bar) ; //=> allways bar
alert(mc1.foo) ; //=> I am mc1
alert(mc2.foo) ; //=> I am mc2
bar belongs to the constructors (MyConstructor) prototype. It will always be 'allways bar', for every instance. foo is an instance property (with a default value 'foo') and can be assigned with a different value for every instance.
Ya prototype of JavaScript is a concept quite similar to class but not exactly the same. Read the article below, it offers one of the best explanations available on internet on this issue.
http://www.crockford.com/javascript/inheritance.html
There are no classes in javascript.
Constructors are functions and have a prototype property that references an object. You can add functions to that object, or assign a new object to the prototype property to create an inheritance chain:
function MyConstructor () {
// initialise instance
}
MyConstructor.prototype.someMethod = function() {
// ...
};
MyConstructor.prototype.anotherMethod = function() {
// ...
};
or replace it with an instance of another constructor:
MyConstructor.prototype = new SomeOtherConstructor();
MyConstructor.prototype.constructor = MyConstructor;
and so on. Now when an instance of MyConstructor is created:
var anInstance = new MyConstructor();
The object returned by the constructor has MyConstructor.prototype as its internal [[prototype]] property and "inherits" its methods and properties (and those on its entire [[prototype]] chain).
So each instance of MyConstructor has its MyConstructor.prototype on its prototype chain. Note however that MyConstructor doesn't inherit from it's own prototype, it is only used by instances created by new MyConstructor.

Categories