I am a beginner to JavaScript and on my way to Prototypes in JavaScript.
As per the article here
Creating a Prototype
The standard way to create an object prototype is to use an object constructor function:
function person(first, last, age, eyecolor) {
this.firstName = first;
this.lastName = last;
this.age = age;
this.eyeColor = eyecolor;
}
With a constructor function, you can use the new keyword to create new objects from the same prototype:
var myFather = new person("John", "Doe", 50, "blue");
var myMother = new person("Sally", "Rally", 48, "green");
The constructor function is the prototype for your person objects.
I find myself confused at the above bold line, which I think is absolutely wrong.
Reason:
alert(person.isPrototypeOf(myFather)); // false
Am I correct to say this as I do believe in this line:
The ‘prototype’ property points to the object that will be assigned as the prototype
of instances created with that function when using ‘new’.
I would agree that terminology is incorrect.
The constructor function has a prototype property which defines the properties and methods in the prototype chain; but it is not itself the prototype of an object, it is the constructor.
isPrototypeOf is not called on the constructor itself, but on the constructor's prototype property.
alert(person.prototype.isPrototypeOf(myFather)); // true
myFather would be an instanceof person, and you can test this using the following line.
alert(myFather instanceof person); // true
I agree with you - the sentence "The constructor function is the prototype for your person objects" is confusing and inaccurate. Instead, your understanding is correct although let me elaborate more.
Basically, whenever you create a function in JavaScript, it will automatically have a property on it called .prototype and the value associated with it will be an object. In your case, the person function also has this .prototype property. When you create new instances of person, each instance will be set up as inheriting from the object associated with the person function's .prototype property - the instance's prototype. This inheritance means that property look-ups are delegated to this prototype object. The key here is that when your person instances look up a property, they will first look up the property on themselves, and if the property isn't found, they will go up the prototype chain.
Looking at your example, here is what is correct:
person.prototype.isPrototypeOf( new person() );
In other words, any instance of person knows to delegate to the object associated with person.prototype whenever the instance can't find a property on itself.
What you are saying,
The ‘prototype’ property points to the object that will be assigned as the prototype of instances created with that function when using ‘new’.
Doesn't make much sense to me, but I think you've got the right idea.
To me, at least,
The constructor function is the prototype for your person objects.
is wrong.
The correct version would be:
The constructor function is the constructor function for your person objects.
The prototype property of your constructor function is an object.
It contains properties which are assigned to objects instantiated with that constructor function, example:
function Person(name){
this.name = name;
}
Person.prototype = {
species: "Human"
};
Sets up a constructor function with a prototype property, containing a property species.
Now, if we do this:
var joe = new Person("Joe");
joe is an object which looks like
{
name: "Joe",
species: "Human"
}
As you can see, the properties of the prototype of Person() were set as normal properties of Joe.
TL;DR
So I think you had the right idea.
Related
I am trying to wrap my head around prototypes, and wold like to know what the prototype is exactly. Much of the confusion stems from not understanding the metalanguage used to describe
prototypes.
Here is what I know:
When we create a named constructor function with properties inside it, the properties inside the body of that constructor function are inherited by object instances created by that constructor function. Here I've created an instance called person001 from the constructor function named Person.
function Person(firstName,lastName) {
this.firstName = firstName;
this.lastName = lastName
}
undefined
var person001 = new Person("John","Doe");
When I look at the object instance in the console and trace the prototype chain, I find it in 2 different places. It is a constructor object of the dunder proto object...
Person {firstName: "John", lastName: "Doe"}
firstName: "John"
lastName: "Doe"
__proto__:
constructor: ƒ Person(firstName,lastName)
__proto__: Object
and a property of the prototype object inside of the same constructor object.
Person {firstName: "John", lastName: "Doe"}
firstName: "John"
lastName: "Doe"
__proto__:
constructor: ƒ Person(firstName,lastName)
arguments: null
caller: null
length: 2
name: "Person"
prototype:
constructor: ƒ Person(firstName,lastName)
__proto__: Object
__proto__: ƒ ()
[[FunctionLocation]]: script.js:76
[[Scopes]]: Scopes[1]
__proto__: Object
When I add a property using the .prototype property of the named constructor function, I am adding that property to the prototype object, NOT to the constructor function. The added property will sit alongside the constructor function in the object of the prototype property. Here I add a property called age using the prototype property of the constructor function Person.
Person.prototype.age = 0;
So now that I've added an additional property, what exactly is the prototype?
When I run the Object.getPrototypeOf method on the object instance person001 it returns what looks to me like the prototype object. It has 3 properties -- a constructor function, the property I added, and the implicit dunder proto object.
Object.getPrototypeOf(person001);
{age: 0, constructor: ƒ}
age: 0
constructor: ƒ Person(firstName,lastName)
__proto__: Object
So what is the prototype? Is it the prototype object {constructor function, additional properties}? Or is it just the constructor function of the prototype object?
Thanks in advance for your assistance.
When you do obj = new Person, there are three players in the game:
the freshly created object obj
the constructor function Person
the prototype, a special hidden object stored under Person.prototype
The relationships between them are as follows:
obj.__proto__ === Person.prototype
Person.prototype.constructor === Person
Illustration:
function Person(firstName,lastName) {
this.firstName = firstName;
this.lastName = lastName
}
var person1 = new Person("John","Doe");
var person2 = new Person("Ann","Smith");
Person.prototype.age = 42;
Said you have created a constructor for a Person and then two instances of it:
const Person = function(name) {
this.name = name;
this.speak = () => console.log('My name is ' + this.name)
};
const john = new Person('John');
const mary = new Person('Mary');
john.speak();
mary.speak();
Now each person you create has a different name, and they can both speak it because they share the same property from some parent object.
But Mary not only can speak. She can sing. But John cannot.
const Person = function(name) {
this.name = name;
this.speak = () => console.log('My name is ' + this.name)
};
const john = new Person('John');
const mary = new Person('Mary');
john.speak();
mary.speak();
mary.sing = () => console.log('♪♪♪ Lalalalalala ♪♪♪');
mary.sing();
john.sing(); // John is such a bad singer, that this throws an error !
What if later on you realize that your people do not only need to speak, but also to walk. You need a reference to their common parent in order to tell them to walk all in one line. That's the prototype. Both Mary and John share a common prototype and have, deep inside, a reference to that prototype (that's __proto__, for friends and family).
const Person = function(name) {
this.name = name;
this.speak = () => console.log('My name is ' + this.name)
};
const john = new Person('John');
const mary = new Person('Mary');
john.speak();
mary.speak();
Person.prototype.walk = () => console.log('I am walking alright');
john.walk();
mary.walk();
// That is the same as:
john.__proto__.walk()
mary.__proto__.walk()
Now John has a bad fall, and it has troubles walking
const Person = function(name) {
this.name = name;
this.speak = () => console.log('My name is ' + this.name)
};
const john = new Person('John');
const mary = new Person('Mary');
john.speak();
mary.speak();
Person.prototype.walk = () => console.log('I am walking alright');
// John's infamous accident
john.walk = () => console.log('My leg hurts so bad...');
john.walk();
mary.walk();
Instance has its own property, we use that.
It has not, we look in its __proto__, and use it if it exists.
Hope this helps!
EDIT: My friend #teemu added to my answer: Every inbuilt object has its prototype.
In very simple language, Every function is a special kind of object in javascript And every function has its own "prototype" object container.
So every constructor function will have its own "prototype" object, which will be shared with all objects in __proto__ constructed using this.
Let's see in example:
// constructor function:
var Person = function(name, age){
this.name = name;
this.age = age
}
var tony = new Person('tony', 21);
var bruce = new Person('bruce', 22);
so as we discussed,
Person.prototype should be the same as tony.__proto__ and bruce.__proto__
note: you can replace Person with inbuilt Array, Object or String also.
to verify this we can do this:
Person.prototype == tony.__proto__; //true
Person.prototype == bruce.__proto__; //true
bruce.__proto__ == tony.__proto__; //true
next thing we are going to do add one property on bruce.__proto__:
bruce.__proto__.isSuperHero = true;
it is same thing when you add properties in prototype
but this will be reflected everywhere;
console.log(tony.__proto__.isSuperHero ) // true
console.log(Person.prototype.isSuperHero) //true
Now you can imagine a prototype as a common space like a house for all family members if any of the family members make changes in that house it will be changed for everyone and every family member can access the house no matter how old he is or he is just a newborn. it will be the same for every family members, stairs will be same, the rooms will be same, the color of the walls will be same.
I hope this will help you in understanding prototype chaining, I tried to explain it in different way which is a better way in my view.
First of all, prototype is just an object. Almost every object in JS (except for eg. when you use Object.create(null)) has some prototype and the prototypes can be chained.
Example: When you create an array by using literal [], your array instance is connected to object (also array instance btw.) defining array's properties like map etc., which itself is connected to another prototype (object instance) defining properties of objects like toString. Those properties are usually functions. Now when you access one of the properties of your object like [].hasOwnProperty, the engine looks up the prototype chain to find it. It start at your [] instance, doesn't find it, continues to the prototype (the array), also without success, so moves to the last prototype (object instance) where it is finally found.
As you can see, prototype chain always ends somewhere, so if you try to retrieve prototype on the last prototype in the chain, you will get null.
Now back to the constructor functions. First thing to note is that those are just normal functions - the actual "creator" of the instance is the keyword new. Now every function has a prototype property which tells you this: Every object created by using this function will get prototype-connected to whatever is in the function's prototype property. By default, every function contains instance of Object in this property, which means that every object you create from this function will be prototype-connected to this instance and will therefore "inherit" properties like toString.
You can see the connection between function's prototype property and instance's prototype in this example.
function A() {}
var a = new A();
a.__proto__ == A.prototype; // is true
Last, the constructor property in the function's prototype property tells you, which function will be used to create new instances when using the function with the new keyword. This mouthful boils down to:
function A() {}
A == A.prototype.constructor; // is true
It is a reference to itself. This property was optional to set when creating your own inheritance chain prior to ES6, but was done nevertheless for correctness' sake.
So what is prototype? It is just an object, connected to other object instances via a special prototype connection, giving it access to predefined properties. It is a way to do inheritance in JS.
I created a Car object like this.
var Car = Object()
Then I added some properties to it like
Car.price = 5000;
Car.color = "red";
Then I created an instance of it like
var car1 = Object.create(Car);
What I don't understand is, when I call car1.prototype or Car.prototype, I get undefined.
According to what I've read, every Object is a prototype of something.
Can someone explain why it's "undefined"?
every Object is a prototype of something
No. Every object has a prototype (except the root object). However, only functions have a prototype property.
The value of that property will become the prototype of the objects that are created by calling the function as constructor function (e.g. var obj1 = new Constr();).
What I don't understand is, when I call car1.prototype or Car.prototype, I get undefined.
As just explained, only functions have a prototype property. car1 and Car are objects and therefore don't have such a property.
To get the prototype of an arbitrary object, you can use Object.getPrototypeOf:
var car1Prototype = Object.getPrototypeOf(car1);
Then I created an instance of it like var car1 = Object.create(Car);
You didn't create an instance of Car. If you created a new object and explicitly set its prototype to Car. Alternatively you could have defined Car as constructor function:
function Car(price, color) {
this.price = price;
this.color = color;
}
var car1 = new Car(5000, 'red');
Now that Car is a function, Car.prototype would yield the prototype of car1, i.e.
Car.prototype === Object.getPrototypeOf(car1);
See also Introduction to Object-Oriented JavaScript
Functions have prototypes. Object instances, like car1, don't.
It's correct to say that every object is a copy of some prototype. By default, objects are a copy of the prototype of the Object "function". However, object instances don't have a prototype themselves.
Think of a prototype as a "model" for a new Object. In Object Oriented languages, a class or a struct act like a strict model for new instances. That is, every instance of the Car class necessarily have motor, for instance. Likewise, in JavaScript, function prototypes act like the "model" for new instances of that function, but they are not strict. Once you create an instance from that model, you can add and remove members, because the language is dynamic.
EDIT
As Pointy clarified, it seems that object instances are not a copy of the "model" function prototype property. It seems that the prototype is copied to an internal object that is looked up when you try to access a property of the instantiated object.
Example:
var car1 = new Car();
// car1 now is not a copy of Car.prototype, but it has an internal object that is.
car1.motor = new V8Motor();
// even though motor is not a property of car1, this will work because JavaScript will find this property in the car1 prototype as it's not a member of the instance itself
Whenever i redefined prototype of function and create an new object of it, its constructor starts pointing to the root Object function instead of the function itself. Let me explain it with scenario:
var Person=function(firstName,lastName)
{
this.firstName=firstName;
this.lastName=lastName;
}
Person.prototype.getFullName=function()
{
return this.firstName+" "+this.lastName;
}
var student=new Person("Ankur","Aggarwal");
student.constructor //shows Person which is correct
After that if I redefined the Person prototype and create a new object of the changed
Person.prototype={}
var manager=new Person('John','Smith');
manager.constructor // Points to Object. Why?
Also if it is pointing to the Object not Person, how come it has the access to the Person properties like firstName and lastName?
Given the constructor:
var Person=function(firstName,lastName)
{
this.firstName=firstName;
this.lastName=lastName;
}
It has a default prototype property that is an object whose constructor property references the Person constructor. It is this property that (by default) instances inherit through the [[Prototype]] chain.
When you create an instance, the firstName and lastName properties are defined on the instance, as if by:
var person = {firstName:..., lastName:...};
so access to those properties is unaffected by the constructor's prototype.
When a new Object is assigned to the constructor's prototype:
Person.prototype = {};
it inherits a constructor property from Object.prototype (which is its constructor). So accessing an instance's constructor first looks on the instance, then on its [[Prototype]] (Person.prototype), then on its [[Prototype]] (Object.prototype) and finds a reference to Object. You can fix that by doing:
Person.prototype.constructor = Person;
You can find more information on MDN: Inheritance and the prototype chain.
Constructing an object does not set its constructor property to the function that constructed it. Instead, a function's default prototype is initialized with a constructor property pointing to that function, and objects constructed by that function inherit the constructor property from the prototype.
When you replace the function's prototype, the replacement does not automatically get that function assigned to its constructor property. Instead, the new prototype inherits constructor from its prototype, which is Object.prototype. Thus, objects created by the function will now inherit a constructor of Object from their grandprototype, Object.prototype.
I've been seeing this pattern in code recently:
function Person(){
this.name = "Dan";
}
Person.prototype = {
whatAmI: function(){
alert("I am a person")
}
}
On the above object person object, you can only reference the function whatAmI by calling Person.prototype.whatAmI() instead of Person.whatAmI() .
Is there any particular reason that this is done? Tt seems like its becoming popular and I cant see the benifit other than having methonds hidden on the prototype object instead of the Person object.
I understand the basics prototypes in Javascript, and I understand that using Person.prototype.whatAmI is a little unconventional in code instaed of just calling new Person(). However, I'm talking about places where the Person object is returned from another function call, and used as a normal object. Thus, the only way to call whatAmI is via Person.prototype.whatAmI
The purpose of the prototype property on functions is that it determines what prototype is assigned to objects created via the new expression when it's used with that function, e.g.:
var p = new Person();
Now, p's underlying prototype is the object that Person.prototype referred to when the new expression was evaluated, so:
p.whoAmI();
works.
In general, replacing the object on the prototype property isn't a great idea and you should only do it when setting up inheritance hierarchies. Instead, just add to the existing object:
function Person(){
this.name = "Dan";
}
Person.prototype.whoAmI = function(){
alert("I am a person")
};
A bit tangential, but:
You do have to replace the object, though, when setting up hierarchies.
// Base
function Person(name) {
this.name = name;
}
Person.prototype.whoAmI = function() {
alert("I am " + this.name);
};
// Derived
function Employee(name, position) {
Person.call(this, name);
this.position = position;
}
Employee.prototype = Object.create(Person.prototype);
Employee.prototype.constructor = Employee;
// Augmenting the derived prototype
Employee.prototype.whatDoIDo = function() {
alert("I hold the position " + this.position);
};
(That's not meant to be the be-all, end-all of hierarchies, just a quick example.)
whatmI is meant to be called on Person instances, e.g.:
var bob = new Person();
bob.whatAmI();
The prototype property of a constructor has properties that are accessible to all constructed instances of that constructor.
The ECMAScript 5 specification has a pleasantly readable explanation of the language's prototype-based inheritance:
Each constructor is a function that has a property named “prototype” that is used to implement prototype-based inheritance and shared properties. Objects are created by using constructors in new expressions; for example, new Date(2009,11) creates a new Date object...
Every object created by a constructor has an implicit reference (called the object’s prototype) to the value of its constructor’s “prototype” property. Furthermore, a prototype may have a non-null implicit reference to its prototype, and so on; this is called the prototype chain. When a reference is made to a property in an object, that reference is to the property of that name in the first object in the prototype chain that contains a property of that name. In other words, first the object mentioned directly is examined for such a property; if that object contains the named property, that is the property to which the reference refers; if that object does not contain the named property, the prototype for that object is examined next; and so on.
Prototype is actually a built in way in JavaScript for accomplishing inheritance. An object that has already been defined can have methods and properties added to it by accessing it's prototype.
Go right to the authority on the subject and read up. This topic in particular is what makes JavaScript cool.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain
There is no specific reason. It depends on what you want.
If the whatAmI function is needed on instances of the type Person, then you define it on the protoype. If you want it on the type, you can do,
Person.whatAmI = function(){
alert("I am a person")
}
They are both valid uses of the language. What you do depends on your application.
I'm studying the concept of inheritance in Javascript, and the tutorial I'm looking at uses this code:
// define the Student class
function Student() {
// Call the parent constructor
Person.call(this);
}
// inherit Person
Student.prototype = new Person();
// correct the constructor pointer because it points to Person
Student.prototype.constructor = Student;
My question is, why is it necessary to both call the parent constructor, Person.call(this), and set the Student prototype equal to a new Person object (i.e. Student.prototype = new Person();)?
There are two separate issues to deal with.
The first is to make sure new Student objects inherit from Person objects. That's why you do Student.prototype = new Person(). That makes the Student.prototype a Person so Student objects will inherit whatever that object inherits (from Person.prototype).
The second is to apply any behavior in the Person constructor to any new Student objects. That's why you do Person.call(this). This is technically not needed if the Person constructor doesn't have any code that modifies the new object, but it's still a good idea to do it just in case you add some code to Person later.
Side note, when setting up the inheritance, it's better to do:
Student.prototype = Object.create(Person.prototype)
...and shim Object.create if needed. This way you don't actually need to invoke the Person constructor in order to get a new object that inherits from Person.prototype. Again, sometimes not an issue, but sometimes there are side effects in the constructor that are undesired when setting up the inheritance.
After doing some testing, to my understanding, the prototype of an object and the property declarations made within its defining function are separate. However, when one constructs a new object, the constructor will pull properties from both the defining function and the prototype of the object being created.
For example,
function Person()
{
this.name = "james";
this.age = "shfifty-five";
}
console.log(Person.prototype.name); // prints "undefined", showing how declaring function Person() and Person.prototype are separate.
Person.prototype.gender = "male";
var human = new Person();
console.log(human.name); // prints "james", showing how the object took properties from declaring function Person().
console.log(human.gender); // prints "male", showing how the object took properties from object prototype Person.prototype.
function Student()
{
this.gpa = 4.00;
}
Student.prototype = new Person();
Student.prototype.constructor = Student;
var myStudent = new Student();
console.log(myStudent.name); // prints "james"
console.log(myStudent.gender); // prints "male"
/*from above two lines, inheritance holds even though 1) Person() defining function was not called inside Student() defining function
and 2) Person() defining function declares properties of Person object.*/
console.log(myStudent.gpa); // prints "4"
As you can see, in this case the defining function Person does alter the properties of its object. But it is still not necessary to call the Person function within the constructor of Student, because the new Person() constructor will pull properties from both Person.prototype and the function Person() defining function.