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.
Related
var Foo = function(){};
Object.defineProperty(Foo.prototype,'x',{
get(){
return 3;
}
});
var foo = new Foo();
console.dir(foo);
The result I am looking for should be
Foo {
__proto__:{
constructor: ƒ (),
x: 3,
__proto__: Object
}
}
But the real result is
Foo {
x: 3,
__proto__:{
constructor: ƒ (),
x: 3,
__proto__: Object
}
}
Why is the x attribute already appearing at the outermost layer?
What Happened (Step-by-step)
var Foo = function(){};
A new function is defined, named - Foo. If we use console.dir(Foo) we will see that Foo has 2 special members prototype and __proto__
Object.defineProperty(Foo.prototype,'x',{
get(){
return 3;
}
});
The prototype of Foo is updated. About defineProperty (From MDN):
The static method Object.defineProperty() defines a new property
directly on an object, or modifies an existing property on an object,
and returns the object.
So the prototype object is now modified with a new member named x. The prototype here acts as a c'tor and will "kick-off" when a new instance of Foo will be created
var foo = new Foo();
A new instance of Foo is created. the c'tor call is using Foo prototype and x getter is applied
Alternatives
Extending Foo prototype, thus making sure it will effect only objects created from Foo (as a class)
Object.defineProperty(Foo.prototype, 'x',
{
get: () => 3
});
console.dir(new Foo().x) // will show 3
console.dir(Foo.x) // undefined - protorype is for class objects
Or extending Foo __proto__, thus updating Foo as a function and while not affecting objectes created from it
Object.defineProperty(Foo.__proto__, 'x',
{
get: () => 3
});
console.dir(new Foo().x) // undefined - x is not a member of Foo
console.dir(Foo.x) // 3
Bonus: a very good article about JS prototypes and why this is happening
Original Answer
This is happening because in JS function is a way to declare BOTH functions and classes!
So your Foo function can be also used as a class
var Foo = function(){};
Foo(); // call Foo as a function
var obj = new Foo(); // initiate an instance from class Foo
Because you are using Foo.prototype object (as a function) and then you create a new instance from your Foo class you guarantee that:
Your function prototype will be modified with your new getter
Every new object (that inherits) from your class will also use your new getter (in object level)
I really think that your code should be something like this instead:
function Foo ()
{
Object.defineProperty(this,'x',{
get(){
return 3;
}
});
}
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
Using JavaScript, is it permissible to use a function as a prototype, e.g.
function Foo(){
}
Foo.prototype = function(){
}
or is it required to use
Foo.prototype = { };
and more importantly, does it make an important difference?
Yes both ways are permissible because of flexibility nature of JavaScript prototypical inheritance. First let's look at the prototypical chain for the both cases. I am considering only literal objects for the simplicity.
Object.prototype vs Function Prototype
The last value of __proto__ (internal [[Prototype]]) for the objects created using literal is Object.prototype eventually. For example:
/*Example 1*/
var o = { foo: 1, bar: 2 }
Prototypical chain: o -> Object.prototype
/*Example 2*/
var o = { foo: 1, bar: 2 }
o.__proto__ = { another:3 }
Prototypical chain: o ->o.__proto__ -> Object.prototype
For functions, the last value of __proto__ is Object.prototype as well except it has always a preceding value Function.prototype. For example:
/*Example 1*/
function Foo () {
return xyz;
}
Prototypical chain: Foo -> Function.prototype -> Object.prototype
/*Example 2*/
function Foo () {
return xyz;
}
Foo.prototype = { another:3 }
Prototypical chain: Foo -> Foo.prototype -> Function.prototype -> Object.prototype
For option 1:
function Foo(){
}
Foo.prototype = function(){
}
As per above discussion, the prototypical chain will be Foo -> Function.prototype -> Object.prototype
For option 2:
function Foo(){
this.name = 'bar';
}
Foo.prototype = { }
and the prototypical chain will be Foo -> Object.prototype
For both cases the prototypical chain is valid and inheritance works correctly without any doubt.
Any object can be a prototype. The prototype can be a plain old object, or a function or an array, which are both objects, or anything else which is an object, including regexps and even dates, not to mention objects wrapping primitives such as numbers and strings and booleans.
But when people talk about using, say, a function as a prototype, they usually intend, or hope, that they can somehow access that function from the instantiated object, but they can't. Instances look up properties on the prototype, whether it be an array or a Date or a regexp or a function or a plain old object, but they can't access the "body" of the prototype object, the thing which in the case of objects based on numbers or strings is called PrimitiveValue.
Here are some examples which might make it clearer, using the simplest case of creating an object based on a prototype with Object.create.
// plain old object prototype
prototype = { a: 42 };
obj = Object.create(prototype);
obj.a // 42
// array as prototype
array = [ 1, 2 ];
obj = Object.create(array);
array.a = 42
obj.a // 42
// NO WAY TO ACCESS [1, 2] from obj
regexp = /foo/;
regexp.a = 42
obj = Object.create(regexp)
obj.a // 42
// NO WAY TO ACCESS regexp from obj
> number = Object(22)
> number.a = 42
> obj = Object.create(number)
> obj.a // 42
// NO WAY TO ACCESS PRIMITIVE VALUE 22 FROM obj
Now let's consider the case of function as prototype. As with the other types of objects
fn = function() { };
fn.a = 42;
obj = Object.create(fn)
obj.a // 42
// NO WAY TO ACCESS fn from obj
However, since fn has its own prototype, including methods such as call, obj also inherits those. So obj.call is defined. However, calling it results in an error because obj is not a function that can be called.
> obj.call()
< Uncaught TypeError: obj is not a function
So the conclusion is that there's nothing particularly wrong or illegal with using a function as a prototype; there's simply no reason to.
In continuation of this question, what is prototype.constructor for?
I thought that by simply doing:
new some_object()
that the function object became a constructor. I don't understand why you would need to set it in this manner.
some_object.prototype.constructor = some_object;
Suppose class A inherit B using the following:
A.prototype = new B();
After this A.prototype.constructor == B. So instances of A have a constructor from B. It's a good practice to reset a constructor after the assignment.
Imagine a function that takes an object and constructs a new instance of that object's type:
function makeNewObjectWithSameType(typedObject) {
return new typedObject.constructor();
}
There is why you might need a constructor property.
But constructor is already set when you define your constructor -- why would you need to define it again? Consider the following case:
function Foo() {
// constructor logic...
}
Foo.prototype.constructor == Foo; // true by default
var f = new Foo();
f.constructor == Foo; // true!
But now consider that Foo.prototype is overwritten:
function Foo() {
// constructor logic...
}
Foo.prototype = {
// new prototype; this is an `Object`
}
Foo.prototype.constructor == Foo; // FALSE! Foo.prototype is an Object
// thus, constructor == Object
var f = new Foo();
f.constructor == Foo; // FALSE! again, this is Object
If you passed in f to my makeNewObjectWithSameType function above, it would construct an Object, rather than a Foo.
You can solve this by manually resetting Foo.prototype.constructor = Foo; after you reassign Foo.prototype to a new object.
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 );