Confusing Javascript prototype behavior - javascript

I have the following Javascript code;
var Person = function(name, age) {
this.name = name;
this.age = age;
return this;
};
Person.prototype.getAge = function() {
alert("Age : " + this.age);
}
var p1 = new Person("xyz",10);
p1.getAge();
This works perfectly and I get the alert as Age : 10
Now if I update the code as below (defined getAge() after instantiating Person object p1);
var Person = function(name, age) {
this.name = name;
this.age = age;
return this;
};
var p1 = new Person("xyz",10);
Person.prototype.getAge = function() {
alert("Age : " + this.age);
}
p1.getAge();
It still returns me the output as "Age : 10"
Now my question is how does this work correctly, since Person.prototype.getAge was defined after we have instantiated Person object p1 ?
Is it because of the way "prototype" works ?

Objects in javascript have a sort of a chain where if you ask them for a property, they will return theirs and if they don't have it, it'll try to find it above its chain, in your case, when p1 is asked for its getAge property, it looks for it in Person.prototype.
var Person = function(name, age) {
this.name = name;
this.age = age;
return this;
};
var p1 = new Person("xyz", 10);
var p2 = new Person("abc", 12);
Person.prototype.getAge = function() {
alert("Age : " + this.age);
}
p1.getAge = function() {
alert("I am " + this.age + " years old.");
}
p1.getAge(); // I am 10 years old.
p2.getAge(); // Age : 12
In this example, p1 has its own getAge property, so when asked, it returns it. On the other hand, p2 doesnt really have this property but can access it via "that chain" and returns the property of its prototype.

Yes that is the way prototype works. You can use this technique to extend strings, objects and arrays too.

Any object prototype can be modified at any time. Think about the libraries/frameworks that modify the base Object prototype...even the built in objects (Date, String, etc) will all have the modifications done to Object.prototype whether or not they happen immediately at page load
try this:
Object.prototype.myTest = function() { console.log('hi'); }
var a = new Date()
a.myTest(); //hi

Related

javascript prototype method not getting result

var Person = function(name,age,job){
this.name = name;
this.age = age;
this.job = job;
}
var dependar = new Person('Dependar',20,'Student');
now that we have created our constructor and all.
I'm trying to use prototype .
Person.prototype.city = 'Delhi';
we have attached new var city to the constructor and all the elements created with it(var dependar)
dependar.city is working properly, it is assigned to 'Delhi'
but when I try to attach a method using prototype
Person.prototype.dob = function(){
this.dob = 2017 - this.age;
}
but when I enter
dependar.dob;
it is displaying the function not the result
function (){
this.dob = 2017 - this.age;
}
What is going wrong? please help
when I enter dependar.dob;it is displaying the function not the result.
REASON:
This is because you have defined it as:
Person.prototype.dob = function(){
this.dob = 2017 - this.age;
}
which is assigning (2017 - this.age) to this.dob .But dob is not defined in the function.
What you can do:
Return value dob directly.
var Person = function(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
}
var dependar = new Person('Dependar', 20, 'Student');
Person.prototype.dob = function() {
return (2017 - this.age);
}
console.log(dependar.dob());
In the console, if you type dependar.dob, or if you use a console.log(dependar.dob), you are getting what you asked for -- the value of dob, which is a FUNCTION and so it does its best to display the contents of that value - the function source code.
To get the function value you need to execute the function, which means dependar.dob() -- note the use of the parens. Those cause the function to execute.

How do I add a method to an existing object? [duplicate]

This question already has answers here:
Javascript add method to object
(4 answers)
Closed 6 years ago.
var Person = function(name, age) {
this.name = name;
this.age = age;
};
//Now create three instances of Person with data you make up
var p1 = new Person('Aaron', 32);
var p2 = new Person('Casey', 30);
var p3 = new Person('Greg',31);
//Now add a sayName method on your Person class that will alert the name of whatever Person instance called it.
I'm not sure how to add a method to an existing class. I'm new to JavaScript. I understand how to add new properties but not new functions.
Add the method to the Person prototype chain.
Person.prototype.sysName = function() {
return console.log(this.name);
};
var Person = function(name, age) {
this.name = name;
this.age = age;
};
Person.prototype.sayName = function () {
alert(this.name)
}
var p1 = new Person('Aaron', 32);
p1.sayName()
You can define Methods in using prototype
Person.prototype.myMethod = function() { ... }
Person.prototype.sayName = function() {
console.log(this.name)
}
you can add a prototype function to the Person class and then each person has access to the function.
One way to do this is by using prototyping you can add a method to an object though doing: myObject.prototype.myMethod = function(){ ... }
Person.prototype.sayName = function(){
console.log(this.name);
}
Another way can be directly adding it on the creation of Person, just note the method is duplicated for each instance in this case:
var Person = function(name, age) {
this.name = name;
this.age = age;
this.sayName = function() {
console.log(this.name);
}
};

Inheritance in Javascript via closure

I'm attempting to learn Javascript inheritance and I've read some resources
Benefits of using `Object.create` for inheritance
How to "properly" create a custom object in JavaScript?
on Stack Overflow about inheriting objects in Javascript to get started.
My goal is hiding private members from outside and I tought that the Closure way of inheriting and creating objects, even if it is not very memory friendly, might help me so I came up with this code:
"use strict";
//State is 'saved' by the closure capturing the value
var Contact = function(address)
{
this.setAddressTo = function(newAddress)
{
address = newAddress;
};
this.getAddress = function()
{
return address;
}
};
var Person = function(name, surname, address)
{
//Superclass 'constructor' which will inherit everything public
Contact.call(this, address);
//Subclass members
this.getName = function()
{
return name;
};
this.setName = function(newName)
{
name = newName;
};
this.getSurname = function()
{
return surname;
};
this.setName = function(newSurname)
{
surname = newSurname;
};
//Also with the prototype chaining I can access superclass methods
this.setAddressTo = function(newAddress)
{
console.log('Setting address from base class');
Person.prototype.setAddressTo(newAddress);
}
}
Person.prototype = Object.create(Contact.prototype);
var p1 = new Person('#1.Name', '#1.Surname', '#1.Address');
var p2 = new Person('#2.Name', '#2.Surname', '#2.Address');
console.log('P1 is a person ? ' + (p1 instanceof Person)); //Yes
console.log('P1 is a contact ? ' + (p1 instanceof Contact)); //Yes
console.log('P2 is a person ? ' + (p2 instanceof Person)); //Yes
console.log('P2 is a contact ? ' + (p2 instanceof Contact)); //Yes
console.log(p1.getAddress()); //'#1.Address'
console.log(p2.getAddress()); //'#1.Address'
p1.setAddressTo('#1.Other_Address');
p2.setAddressTo('#2.Other_Address');
console.log(p1.getAddress()); //'#1.Other_Address'
console.log(p2.getAddress()); //'#2.Other_Address'
//Should be undefined because it is not accesible
console.log(p1.address);
console.log(p2.address);
The line:
Person.prototype = Object.create(Contact.prototype);
I use it for making the 'instanceof' operator working correctly (which means that a Person object is an instance of Person and Contact)
Is it correct to do this ?
These lines:
var p1 = new Person('#1.Name', '#1.Surname', '#1.Address');
var p2 = new Person('#2.Name', '#2.Surname', '#2.Address');
Is correct calling the function Person() with 'new' ?
To me it makes sense because I will receive a new Object with its prototype set to Person.prototype which has its prototype set to Contact.prototype (I guess) and this will make the newly created object effectively a Person.
The approach that I've posted is valid to achieve inheritance correctly in Javascript or other better best practices exists to achieve the same thing ?

New Object Creation issues

Ok so the following function acts as a constructor to create an Employee object(no problem with that). But when I use this function to create 3 new employees I am messing up somewhere.
I know I'm supposed to set the properties and print the employee's name and phone number, but I am missing something or something is in the wrong place.
Thanks in advance for your help.
function Employe() {
var = name;
var = phone;
this.getName = function () {
return this.name;
}
this.setName = function (name, phone) {
this.name = name;
this.phone = phone;
};
}
var emp1 = newEmployee;
this.Name = 'jo';
this.Phone = ' 555-5551'
document.write(Employee.name Employee.phone);
var emp2 = newEmployee;
this.Name = 'jim';
this.Phone = '555-5552';
document.write(Employee.name Employee.phone);
var emp3 = newEmployee;
this.Name = 'jon';
this.Phone = '555-5553';
document.write(Employee.name Employee.phone);
In the following:
> var emp1 = newEmployee;
The variable on the left will be assigned the result of evaluating the expression on the right. There is no identifier newEmployee, so you will get an error. What you probably meant to write is:
var emp1 = new Employee();
That will call the constructor, which will return a new instance, a reference to which will be assigned to emp1.
Then you have:
> this.Name = 'jo';
The value of this is set when entering an execution context. For global code, it always references the global object (which is equivalent to window in a browser). So the above line creates a Name property of the global object and assigns the value 'jo';
What you wanted is probably:
emp1.setName('jo','555-5551');
The name of that method seems inappropriate given that it sets both the name and phone number.
> document.write(Employee.name Employee.phone);
Since you added the properties to the instance (emp1), likely that's the properties you want to read:
document.write(emp1.name + ' ' + emp1.phone);
or to use the getName method:
document.write(emp1.getName() + ' ' + emp1.phone);
and so on.
There's a lot wrong with your code example. The constructor is misspelled. The employee instances should be created like:
var emp1 = new Employee();
The instance properties should be set like:
emp1.setName('John');
You've also combined two setters into one, which is confusing.
To access the instance properties, you should use:
emp1.getName();
Not:
Employee.Name
Yes you have a lot of errors I think this is basically what you want to achieve.
function Employee(){
this.name;
this.phone;
this.getName = function(){
return this.name;
};
this.setName = function(name, phone){
this.name = name;
this.phone = phone;
};
}
function employ(){
var emp1 = new Employee();
emp1.name = 'jo';
emp1.phone = ' 555-5551' ;
alert(emp1.getName());
}
http://jsfiddle.net/umNTs/

implementing javascript inheritance

I am trying to understand inheritance in javascript
function baseClass(name) {
this.name = name;
this.getName = function() {
return this.name;
}
}
function subClass(id, company){
baseClass.call(this);
this.id = id;
this.company = company;
this.toString = function() {
return name + "\n" + this.id + "\n" + this.company;
}
}
subClass.prototype = Object.create(baseClass);
var s = new subClass();
s.toString(); //here the name property from the baseClass is not displayed.
How do correctly implement inheritance (classical / prototypical)
First, there are two minor issues:
Casing matters in JavaScript. Object.create needs to be lowercased, and your function names don't match (subClass vs SubClass). Usually, constructor function names are uppercased.
Use the property this.name (which is inherited) instead of the variable name (which is undefined) - see Javascript: Do I need to put this.var for every variable in an object?
How do correctly implement inheritance
Move the methods (which don't need to privileged, there are no local variables in the constructor scope) on the prototype objects. And let SubClass.prototype inherit from BaseClass.prototype, not from the BaseClass function.
function BaseClass(name) {
this.name = name;
}
BaseClass.prototype.getName = function() {
return this.name;
};
function SubClass(id, company){
BaseClass.call(this);
this.id = id;
this.company = company;
}
SubClass.prototype = Object.create(BaseClass.prototype);
SubClass.prototype.toString = function() {
return this.name + "\n" + this.id + "\n" + this.company;
};
new SubClass().toString() does not display the name property from the baseClass
You're calling the constructor without any arguments. The id, company and name properties will have the undefined value. Also, your SubClass doesn't even have a parameter for the name, and it doesn't pass anything to the BaseClass constructor invocation.

Categories