I'm studying javascript and have a trouble to understand the 2nd part in the explanation below. Is it possible for any of you shed me the light on this matter
"The actual prototype of a constructor is function.prototype since constructors are functions. Its prototype property will be the prototype of instances created through it but is not its own prototype"
I think a series of comparisons will help you figure it out.
The actual prototype of a constructor is function.prototype since constructors are functions
function IamAConstructorFunc() {} // A constructor function
IamAConstructorFunc.constructor // function Function()
IamAConstructorFunc.constructor.prototype // function Empty()
IamAConstructorFunc.constructor.prototype === Function.prototype // True
IamAConstructorFunc.constructor.prototype === Object.prototy // False
Its prototype property will be the prototype of instances created through it
var IObj = new IamAConstructorFunc; // Instance of IamAConstructorFunc
IObj.__proto__ === IamAConstructorFunc.prototype // True
IObj.constructor === IamAConstructorFunc // True
IObj instanceof IamAConstructorFunc // True
but is not its own prototype
IamAConstructorFunc has a prototype but it's not it's own prototype, it's an instance of Object and that instance prototype is:
IamAConstructorFunc.prototype.__proto__ === Object.prototype // True
OK, here's an example:
function Widget() {
console.log('Widget constructor invoked');
}
Function.prototype.sayHi = function() { console.log('Function prototype.sayHi invoked'); };
Widget.prototype.sayHi = function() { console.log('Widget prototype.sayHi invoked') };
var w = new Widget();
console.log('Calling w.sayHi()');
w.sayHi();
console.log('Calling Widget.sayHi()');
Widget.sayHi();
This will produce the following log output:
Widget constructor invoked
Calling w.sayHi()
Widget prototype.sayHi invoked
Calling Widget.sayHi()
Function prototype.sayHi invoked
Calling w.sayHi() is calling a method on the Widget object, while calling Widget.sayHi() is invoking a method on a function. They have two different prototypes.
That's way too complicated.
A function can be used to create an object.
function MyFunc(a, b) {
this.a = a;
this.b = b;
}
var myObj = new MyFunc(a, b);
The function's prototype can be used to create functions that work on the object.
MyFunc.prototype.sum = function() {
return this.a + this.b;
}
var myObj = new MyFunc(2, 3);
var true = (myObj.sum() === (2 + 3));
It's probably easier viewing an example.
function Person(first, last) {
this.first = first;
this.last = last;
}
Person.prototype.fullName = function() {
return this.first + " " + this.last;
}
var fred = new Person("Fred", "Flintstone");
var barney = new Person("Barney", "Rubble");
var output = document.getElementById("output");
output.innerHTML += fred.fullName() + "<br>\n";
output.innerHTML += barney.fullName() + "<br>\n";
#output {
color:blue;
font-weight:bold;
}
<div id="output">
</div>
I think the problem is the confusion between the prototype property of a function and the internal prototype, that every object has.
Every function has a prototype property. This property is like any other property of any object. The only thing special about it is, that it will be used as the internal prototype for any object, that is created by that function.
function A() {
}
//add property c to public prototype property of A
A.prototype.c = 1;
//create a new instance -> a will get A's prototype property as internal prototype
a = new A();
//a has therefore access to the property c, that was defined earlier
console.log(a.c); //1
Since functions are also objects in JavaScript, they also have an internal prototype.
function A() {}
//apply is part of A's prototype chain.
//It's defined on its internal prototype objects,
//which was created by its own constructor, named "Function"
A.apply(this, []);
This statement almost drove me crazy but I ended up understanding it. In fact, in JavaScript, a constructor, when created get automatically assigned a property called prototype.
This property will be used by all instances created through this constructor as their own prototype and DOES NOT REFER ANYWAY TO the actual prototype of the constructor itself. Actually, the constructor prototype is Function.prototype.
var Cat = function() {};
Cat.__proto__ === Function.prototype; // true
var kitty = new Cat;
kitty.__proto__ === Cat.prototype; // true
It is normal because the Cat (our constructor) is a Function per se so it derived from Function.prototype. And kitty came out of the new keyword call on Cat so it derived from Cat.prototype.
So in the statement :
The actual prototype of a constructor is function.prototype since constructors are functions.
The actual prototype refers to __proto__ property of our constructor (Cat).
Its prototype property will be the prototype of instances created through it but is not its own prototype.
Its prototype property refers to .prototype
Related
Consider the first scenario:
function f(){
console.log("inside the function : " + f.myVar);
}
f.prototype.myVar = 1;
var myObject = new f();
console.log("from the object : " + myObject.myVar);
And this is the output:
inside the function : undefined
from the object : 1
Question: why myVar isn't available in function? If it is stored in the objects prototype it is supposed to be accessible in f().
Now this scenario:
function f(){
console.log("inside the function : " + this.myVar);
}
f.prototype.myVar = 1;
var myObject = new f();
console.log("from the object : " + myObject.myVar);
And the output:
inside the function : 1
from the object : 1
Question: Why I'm getting different result? if 'this' refers to the object doesn't f.myVar mean access myVar in myObject ?
And now this scenario:
function f(){
console.log("inside the function : " + f.myVar);
console.log("inside the function using 'this' : " + this.myVar);
}
f.myVar = 1;
var myObject = new f();
console.log("from the object : " + myObject.myVar);
output:
inside the function : 1
inside the function using 'this' : undefined
from the object : undefined
So if I set a property without using prototype it should'nt be available in instantiated objects. But if I write the script like this, it'll deliver a strange result:
function f(){
console.log("inside the function : " + f.myVar);
}
f.myVar = 1;
var myObject = new f();
console.log("from the first object : " + myObject.myVar);
var strangeObject = myObject.constructor;
console.log("from the strange object : " + strangeObject.myVar);
Output:
inside the function : 1
from the first object : undefined
from the strange object : 1
Where does that "f.myVar" store? Whose variable is that? I'm confused what is the difference between all scenarios above. A complete carification would be much appreciated.
EDIT:
The main problem is that I don't know what this exactly mean:
function f(){}
f.someVar = someValue;
Because in other languages function is an abstract concept and in fact doesn't exist until it is called. Now in JS it is said that functions are objects by default. Ok so I should have an object like this by the script above:
{someVar : sameValue}
in fact I think this should be as same as:
function f(){this.someVar = someValue;} //should create {someVar : someValue}
If this is the case EVERY object instantiated by calling "new f()" must contain this "someVar" but they don't.
Start out by examining the definition of the word prototype. I think it's important to keep this in mind when thinking about how new objects are created in JavaScript.
pro·to·type
noun
a first, typical or preliminary model of something, especially a machine, from which other forms are developed or copied.
verb
make a prototype of (a product).
A prototype is a model from which another form will be copied.
When you create a new object in JavaScript, that is exactly what happens.
var obj = new MyObject();
In the above code, there are many things that happen, but in the context of the question, there are two things that happen which are relevant:
The prototype is applied to a new object.
The function MyObject is called, with this set to the new object.
With this knowledge in mind, let's take a look at the different forms of setting variables you have described:
function MyObject() {}
MyObject.myProperty = 'MyProperty';
It's important to understand that functions themselves are objects in JavaScript. Therefore, function MyObject is an object instance to itself. On the second line, we have set the property myProperty on this function object.
Refer back to the steps of creation above, and you will notice that it does not include applying properties from the function object to the new instance object. It only applies properties from the function object's prototype, and then runs the body of the function with this set to the new instance.
function MyObject() {
this.myProperty = 'MyProperty';
}
Here, the property myProperty is set on the individual instance.
function MyObject() {}
MyObject.prototype.myProperty = 'MyProperty';
In this example, each new instance of MyObject will be given its own property called myProperty and the value set to 'MyProperty'. From there, each instance can change its own myProperty to whatever value it needs without affecting the other.
function MyObject() {
console.log('myProperty', this.myProperty); //Will output 'Outside constructor.'
this.myProperty = 'Inside constructor.';
console.log('myProperty', this.myProperty); //Will output 'Inside constructor.
}
MyObject.prototype.myProperty = 'Outside constructor.';
The above example shows how myProperty is first applied from the prototype, then overwritten by the value applies in the function that is run.
Let's take a look at an example with all the forms you mentioned:
var output1 = document.getElementById('output1'),
output2 = document.getElementById('output2'),
output3 = document.getElementById('output3');
function MyObject(myProperty) {
this.myProperty = myProperty;
}
MyObject.myProperty = 'Function property.';
MyObject.prototype.myProperty = 'Prototype property.';
var obj = new MyObject('Constructor property');
output1.innerHTML = obj.myProperty;
output2.innerHTML = MyObject.myProperty;
output3.innerHTML = MyObject.prototype.myProperty;
<div id="output1"></div>
<div id="output2"></div>
<div id="output3"></div>
In the above example, you'll see how each can be referenced. Now examine it a little closer. Take a look at what happens with your 'Function property' when it is set from two different object instances:
var output1 = document.getElementById('output1'),
output2 = document.getElementById('output2');
function MyObject() {
//We are concatenating a string to the end of the property on each function call.
MyObject.myProperty += ' test ';
}
MyObject.myProperty = 'Function property.';
var obj1 = new MyObject();
var obj2 = new MyObject();
output1.innerHTML = MyObject.myProperty;
output2.innerHTML = MyObject.myProperty;
<div id="output1"></div>
<div id="output2"></div>
The above code demonstrates how the function level property is effectively shared. That's because it's not part of each instance. It's part of the function object.
Here I'll show you the process that takes place with the new operator, without actually using the new operator:
var output = document.getElementById('output');
//Let's have an object that has a prototype property with some properties:
var MyPrototypeObject = {
prototype: {
myPrototypeProperty: 'Prototype property'
}
};
//Let's specify a function that will be used as a constructor:
function MyConstructorFunction() {
this.myInstanceProperty = 'Instance property';
}
//First, new creates an object
var obj = {};
//Next, it applies all the properties from the prototype. We are using the MyPrototypeObject's prototype property for this example
for (var key in MyPrototypeObject.prototype) {
var val = MyPrototypeObject.prototype[key];
//Set the same property on the new object.
obj[key] = val;
}
//Now the prototype has been applied, let's apply the constructor function that was called.
MyConstructorFunction.call(obj); //This calls MyConstructorFunction with this set to obj.
output.innerHTML = 'myPrototypeProperty: ' + obj.myPrototypeProperty + '<br>' + 'myInstanceProperty: ' + obj.myInstanceProperty;
<div id="output"></div>
why myVar isn't available in function? If it is stored in the objects
prototype it is supposed to be accessible in f().
It's accessible in the function, but not as f.myVar, but as this.myVar or f.prototype.myVar.
Why I'm getting different result? if 'this' refers to the object
doesn't f.myVar mean access myVar in myObject ?
The function f is not the same as the object instance. The function is the constructor for the object, and using it with the new keyword creates an instance that is a separate object from the function.
When you use f.var, that is the property var of the function object. When you use this.var in the function, that is the property var in the object instance that the use of the new keyword created.
If you use f.var, that is a property of the constructor function object, so it will be the same variable even if you create multiple instances of the object, and it's only accessible using f.var.
If you use f.prototype.var, that will also be a variable that is the same for all instances of the object, but that can also be accessed using this.var as the object inherits the members of the prototype.
Example:
function f() {
console.log(f.var); // shows "42"
console.log(f.prototype.var); // shows "0.01"
console.log(this.var); shows "0.01";
}
f.var = 42;
f.prototype.var = 0.01;
If you want a variable that is local to each instance of the object, you should use neither of those. You should assign a value to this.var, which will make it a property in the object instance.
Example:
function f(value) {
this.var = value;
}
f.prototype.getValue = function(){
return this.var;
};
var instance1 = new f(42);
var instance2 = new f(0.01);
// now you have two instances with separate values:
console.log(instance1.getValue()); // shows "42"
console.log(instance2.getValue()); // shows "0.01"
As for question in edit, really all simple :-)
you have a function object function f(){}
you add to this object property, like you can add property to any other object in javascript f.someVar = 1
this not same as function f(){this.someVar = someValue;} because this in javascript depends on how function calling and can refers to created object, global object, or something else if called with call or apply function.
When you create object with new operator - you call f as constructor, and in this case this inside function referes to created object, and all properties added inside function as this.something = val add to created object.
Note: that you not use any property from function directly, so this not added to created object.
As for prototype: when you create object - you just set prototype property of created object to f.prototype object. So at end when you create object, you not use any property directly added to function object, just property from prototype and property that added manually to this in constructor
Seems you are getting confused with the prototype of function and object.
Here's a quote from the book Eloquent Javascript explaining the difference:
It is important to note the distinction between the way a prototype is
associated with a constructor (through its prototype property) and the
way objects have a prototype (which can be retrieved with
Object.getPrototypeOf). The actual prototype of a constructor is
Function.prototype since constructors are functions. Its prototype
property will be the prototype of instances created through it but is
not its own prototype.
in this case
var A = function(){
this.d = 123;
}
A.prototype.c = 999;
A.prototype.d = 333;
var B = (new A()).constructor;
console.log(""+B);
console.log(new A().d); // 123
console.log(new B().d); // 123
console.log(new A().c); // 999
console.log(Object.getPrototypeOf(new B()).c); // 999 why?
A and B share same constructor
but B is not A, why has same prototype of A?
in this case
var A = function(){
this.d = 123;
}
A.prototype.c = 999;
A.prototype.d = 333;
var B = A.constructor;
console.log(""+B);
console.log(new A().d); // 123
console.log(new B().d); // undefined
console.log(B.d); // still undefined
console.log(new A().c); // 999
console.log(Object.getPrototypeOf(new B()).c); // undefined
B is constructor of A and not of his instance
what is B? how to access constructor of A with no instance of A?
When you call new A(), you create a new A object whose prototype is A.prototype. When you ask for (new A()).constructor, you're accessing the constructor property from the prototype chain of that A instance; this would be A.prototype.constructor.
A itself is a Function object. That is to say: A is an instance of Function. When you ask for A.constructor, you're accessing the constructor property from the prototype chain of that Function instance; this would be Function.prototype.constructor.
In your first case, B and A are references to the exact same function. It's totally expected that the results of new A() and new B() would have the same properties and the same prototype chain.
In your second example, B is the Function constructor -- i.e., a function that constructs functions. Calling new B() creates a new Function object. Thus, the result of new B() has none of the same properties as an A instance.
To tell the difference you might want to look at what is A and what is new A():
c = new A(); // This is an instance of A. The constructor property is A.
console.log(c.constructor) // function() { this.d = 123; }
console.log(new c.constructor()) // Creates another instance of A.
console.log(Object.getPrototypeOf(new c.constructor())) // A {c: 999, d: 333}
var c = A; // This is a function. The constructor property is a base Function.
console.log(c.constructor) // function Function() { [native code] }
console.log(new c.constructor()) // Creates instance of base Function.
console.log(Object.getPrototypeOf(new c.constructor())) // function Empty() {}
Without the new operator on your custom constructor (A) you are not creating an instance of A.
More information on new operator: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new
Even though it's already answered, I did not see it made clear that B is A (oops, its late missed apsillers mentioned it):
var A = function(){};
var B = (new A()).constructor;
console.log(B===A,B===A.prototype.constructor
,A.prototype.constructor ===A);//true true true
//Something.prototype.constructor is a circular reference as constructor
//references Something
console.log(A.prototype.constructor.prototype.constructor.prototype
.constructor.prototype.constructor === A);//true
Constructor comes with prototype and is set to the constructor function but you can overwrite it (usually done when inheriting so you usually see it repaired after inheriting)
Child.prototype=Parent.prototype;
//Child.prototype.constructor now incorrectly refers to Parent
console.log(Child.prototype.constructor===Parent);//true
//repair constructor
Child.prototype.constructor=Child;
More on inheritance, constructor functions and prototype here.
Since all objects have a prototype (unless created with Object.create(null)) all objects have a constructor property pointing to the function that created them:
console.log([].constructor===Array);
var arr = new [].constructor(1,2,3);//same as new Array(1,2,3)
console.log(arr);//[1,2,3]
//the following temporarily casts the string to String
console.log("hello".constructor===String);//true
//same with numbers
console.log(1..constructor===Number);//true
console.log(function(){}.constructor === Function);//true
var someObj = function() { }
var p = new someObj();
alert(someObj.prototype); // This works
alert(p.prototype); // UNDEFINED, but why?
someObj.prototype.model= "Nissan";
alert(p.model); // This works! I understand the dynamic nature of prototypes, but doesn't that mean that p.prototype === someObj.prototype?
Why is this so? Since "p" is an instance of "someObj", why is the prototype undefined? I mean, when I add a property to "someObj" prototype, it is accessible to "p", so why is the prototype not accessible?
The important thing here is that the prototype property of function objects is not the prototype of an object. It's the object that will be assigned as the prototype of an object you create via new someObj. Prior to ES5, you can't directly access the prototype of an object; as of ES5, you can, via Object.getPrototypeOf.
Re
alert(p.prototype); // UNDEFINED, but why?
The reason is that the p object doesn't have a property called "prototype". It has an underlying prototype, but that's not how you access it.
All function objects have a property called prototype so that if they're used as constructor functions, we can define what the properties of the underlying prototype of the objects created by those constructors will be. This may help:
function Foo() {
}
Foo.prototype.answer = 42;
console.log(Foo.prototype.answer); // "42"
var f = new Foo();
console.log(f.answer); // "42"
That last line works like this:
Get the f object.
Does f have its own property called "answer"?
No, does f have a prototype?
Yes, does the prototype have its own property called "answer"?
Yes, return the value of that property.
You've mentioned Object.create in the title of your question. It's important to understand that Object.create is quite separate from constructor functions. It was added to the language so that if you preferred not to use constructor functions, you didn't have to, but could still set the prototype of an object — directly, when you create that object.
That's because prototype is a property of the constructor function, not a property of itself. However, the prototype object has a reference to the constructor, so you can access an object's prototype via its constructor property:
function Foo() {}
Foo.prototype.foo = "bar";
var c = new Foo;
console.log( c.constructor === Foo ); // true
console.log( c.constructor.prototype ); // { foo: 'bar' }
However, this will not work if you overwrite the initial prototype property of the constructor function:
function Foo() {}
// I overwrite the prototype property, so I lose the initial reference
// to the constructor.
Foo.prototype = {
foo: "bar"
};
var c = new Foo;
console.log( c.constructor === Foo ); // false
console.log( c.constructor === Object ); // true
console.log( c.constructor.prototype ); // {}
That's why you're better off using the new Object.getPrototypeOf method introduced in ES5.
function Foo() {}
Foo.prototype = {
foo: "bar"
};
var c = new Foo;
console.log( c.constructor === Foo ); // false
console.log( c.constructor === Object ); // true
console.log( c.constructor.prototype ); // {}
console.log( Object.getPrototypeOf(c) ); // { foo: 'bar' }
Another solution would have been to make sure you restore the constructor reference on the prototype:
function Foo() {}
// Overwriting the initial prototype
Foo.prototype = {
constructor: Foo, // restore the constructor reference
foo: "bar"
};
p.prototype doesn't work because in this case p = someObj.prototype.
Basically when you use the new operator what happen is that the constructor someObj is used to initialize a new object. Which means it returns an object which have the properties and methods of the prototype of the constructor.
Thus p = someObj.prototype and p.prototype is undefined as p is not a constructor.
This article might help explains this more
http://www.htmlgoodies.com/html5/tutorials/javascript-prototypical-inheritance-explained.html#fbid=A2ikc3JLxeD
p is an instance of someObj. The prototype belongs to the constructor. You can retrieve p's constructor prototype using p.constructor.prototype
In Javascript, constructors, and in fact all functions get a prototype property. An objects (that is, a set of key-value pairs), does not have a prototype property. In your example above,
var someObj = function() { } // this is a function, so it has a prototype property
var p = new someObj(); // this is an instance object, so it doesn't
That's why someObj.prototype is defined, but p.prototype is not.
I've recently started reading up on OOP javascript and one thing that authors seem to skip over is when an object A has been declared and suddenly I see "A.prototype.constructor =A;
For example,
var A = function(){}; // This is the constructor of "A"
A.prototype.constructor = A;
A.prototype.value = 1;
A.prototype.test = function() { alert(this.value); }
var a = new A(); // create an instance of A
alert(a.value); // => 1
So I run the command in firebug "var A = function(){};"
and then "A.Constructor" Which reveals it's a function. I understand this.
I run the code "A.prototype.constructor = A;" and I thought this changes the A constructor from Function to A.
The constructor property of A has been changed right? Instead when I run "A.constructor" it gives me function () still.
What's the point?
I also see A.constructor.prototype.constructor.prototype.. what is going on?
If A inherit B using A.prototype = new B();, you need to reset the constructor property for the class A using A.prototype.constructor=A;, otherwise instances of A would have a constructor of B.
In your case, A.prototype.constructor === A will return true, so A.prototype.constructor = A did nothing.
You can quickly test out that that additional assignment does absolutely nothing:
var A = function() {};
A.prototype.constructor === A; // true -- why assign then?
Resetting the constructor property only makes sense if you've assigned a new prototype object to the class, overwriting the original constructor:
var A = function() {};
A.prototype = protoObject; // some object with members that you'd like to inherit
A.prototype.constructor = A; // reset constructor
In your case, the author might be blindly doing this as good practice, even in cases where it's not necessary.
This code if often use in JS classic inheritance pattern (the code is from JavaScript Patterns by Stoyan Stefanov):
function inherit(C, P) {
var F = function () {};
F.prototype = P.prototype;
C.prototype = new F();
C.uber = P.prototype;
C.prototype.constructor = C;
}
to assign right constructor to the child class.
In your case it did nothing, since A.prototype.constructor === A before assignment.
You might want to see my answer to similar question:
https://stackoverflow.com/a/19616652/207661
TL;DR: constructor is not an own property of an instance. So to make things look consistent JavaScript interpreter needs to set prototype.constructor to function itself. This feature can be used in functions that operates generically on many different types of objects.
According to MDN, All objects inherit a constructor property from their prototype:
Example 1:
var o = {};
o.constructor === Object; // true
..
Example2:
function Tree() {
}
var theTree = new Tree();
console.log(theTree.constructor === Tree ); // true
At runtime, it does not make any difference based on the value of the constructor property.
However, as the constructor property returns a reference to the Object function that created the instance's prototype, one should reset the constructor property when they assign a new prototype to the Object function.
var Forest = function() {};
Forest.prototype = theTree;
console.log(new Forest().constructor === Tree ); // true
Forest.prototype.constructor = Forest;
console.log(new Forest().constructor === Forest ); // true
https://jsfiddle.net/j1ub9sap/
For details: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor
In Javascript’s system of prototypal inheritance, an object’s internal prototype reference is set to its constructor’s “prototype” property, which is itself an object.
Properties of the constructor’s “prototype” property may be resolved as if they were properties of object instances. However, the actual properties of the constructor object are not accessible to the instance:
function MyConstructor() { }
MyConstructor.x = 3
MyConstructor.prototype.y = 7
a = new MyConstructor()
a.x == 3 // FALSE
a.y == 7 // TRUE
However, if the property (“x”) of the constructor is declared in the function body with the this keyword, these properties are of course resolved by instances:
function MyConstructor() {
this.x = 3
}
MyConstructor.prototype.y = 7
a = new MyConstructor()
a.x == 3 // TRUE
Why? What is the difference?
When you do this:
MyConstructor.x = 3;
...you've only added a property to the Function object instance referenced by MyConstructor. A Function object has many properties that do not become part of the instance (nor would you want them to).
As such, the mechanism for creating instance properties via the constructor is to use the this.x method.
When the constructor runs, this is the object that is being returned. So it is just a convenience so you don't have to do:
a = new MyConstructor();
a.x = 3;
a.x == 3 // TRUE!
Because this in the constructor is the same as the resulting object, there's no need to do it explicitly upon each new instance creation.
The prototype object is simply an object that is referenced by all instances of MyConstructor so if there isn't a property on the instance, it then goes to the prototype to find one.
To illustrate the relationship between this and the new instance, consider this example:
Example: http://jsfiddle.net/M2prR/
var test; // will hold a reference to "this"
function MyConstructor() {
test = this; // make "test" reference "this"
}
// create a new instance
var inst = new MyConstructor;
// see if they are the same object. This will alert "true"
alert( inst === test );