I am trying to figure out what 'this' is referencing in my last function (Mamamal.prototype.haveBaby);
var Mammal = function(name){
this.name = name;
this.offspring = [];
};
// var myMammal = new Mammal('Joe');
Mammal.prototype.sayHello = function(){
return 'My name is ' + this.name + ", I'm a Mammal";
};
Mammal.prototype.haveBaby = function(){
debugger;
var childName = "Baby " + this.name;
baby = new this.constructor(childName); //new Cat OR new Mammal
baby.name = childName;
this.offspring.push(baby);
return baby;
};
I am not sure why the syntax
baby - new this.constructor(childName);
is this Mammal.prototype?(then constructor so it would be Mammal.prototype.constructor(childName); That's the only way I know how to set the constructor. Mammal.constructor wouldn't work.
The value of this depends on how a function is called, in your case Mammal.prototype.haveBaby.
If you call it with Mammal.prototype.haveBaby(), then this refers to Mammal.prototype.
If you call it as instance methods (which is more likely), e.g.
var mammal = new Mammal();
var baby = mammal.haveBaby();
then this refers to mammal.
But in both cases you are accessing the same property, since every instance of Mammal inherits the properties of Mammal.protoype. So this.constructor === Mammal.prototype.constructor, no matter in which situation of those two.
Read the MDN documentation for more information about this.
Related
I am new at learning JavaScript concepts. Want to understand how prototypical inheritance work. My impression was if your class inherits its parent, and you have a same named method in prototypes of both classes, when you call the method on child instance, the method in the child prototype will be called.
Code:
function Animal(name) {
this.name = name;
}
Animal.prototype.printName = function () {
console.log(this.name + ' in animal prototype');
}
function Cat(name) {
Animal.call(this, name);
}
Cat.prototype.printName = function () {
console.log(this.name + ' in cat prototype');
}
Cat.prototype = Object.create(Animal.prototype);
var anm1 = new Animal('mr cupcake');
anm1.printName();
var cat1 = new Cat('cat');
cat1.printName();
On calling cat1.printName() I expected it to log 'cat in cat prototype' but it logged 'cat in Animal prototype'. Could someone please explain the reason to me. Thanks.
You are correct, but your override of the printName() function is, itself, being overridden by the next line when you reset the Cat.prototype. Simply moving the order of the code fixes the issue:
function Animal(name) {
this.name = name;
}
Animal.prototype.printName = function() {
console.log(this.name + ' in animal prototype');
}
function Cat(name) {
Animal.call(this, name);
}
// OLD LOCATION of code
// This was overriding your override!
// Setting the prototype of an object to another object
// is the basis for JavaScript's prototypical inhertiance
// This line replaces the existing prototype object (which is
// where your override was) with a completely new object.
Cat.prototype = Object.create(Animal.prototype);
// NEW LOCATION
// AFTER setting the prototype (and creating inheritance),
// it is safe to do the override:
Cat.prototype.printName = function() {
console.log(this.name + ' in cat prototype');
}
var anm1 = new Animal('mr cupcake');
anm1.printName(); // "mr cupcake in animal prototype"
var cat1 = new Cat('cat');
cat1.printName(); // "cat in cat prototype"
I have read a few questions like this about it, but I still can't make it work:
Here is my simplified test:
var person = function(name, job)
{
var self = this;
self.name = null;
self.callMe = function()
{
alert(self.name + ' please!');
};
self.init = function()
{
self.name = name;
setTimeout(function(){self.callMe()}, 1000);
}();
}
...
person.prototype.callMe = function()
{
alert('Mister ' + this.name + ' please!');
};
var jonh = new person('john');
var joe = new person('joe');
can test it here: http://codepen.io/anon/pen/bqxmPa?editors=0010
1. Why is the callMe() function in use the original one?
I have read that I must use this to be able to use prototype, which makes sens: since I call a function stored in var self from self.init() the function stored in that var will not be modified by my later prototype... But then how do I do the callback if I don't store the this in self?
2. If I override callMe like person.callMe = function(){}; it will do the same, then why should I use prototype?
I also understand that placing a method in a prototype is good for performance as it is not duplicated in each instance but still shared among them.
Thanks for your teaching!
1.) This is how prototypical inheritence works. When the callback for callMe returns, the code tries to resolve the variable self inside the callback's execution context. Since it is not defined there, it goes up the prototype chain and finds it defined in the execution context on the same level where the callMe and init functions are defined. As callMe is defined on this level, it will simply execute it. If it was not defined on this level, it would execute the function defined on the prototype.
2) If you want to subscribe to OO JS, putting the functions on the prototype will make it clear that they are uhh 'interface methods'. What you are doing here is effectively defining instance methods everytime you 'new' up a class.
Here's how I would implement the Person class as OO
var Person = function(name, job){
this.name = name;
this.init();
};
Person.prototype.init = function(){
setTimeout((function() {
this.callMe();
}).apply(this), 1000);
};
Person.prototype.callMe = function(){
alert('Mister ' + this.name + ' please!');
};
var jonh = new Person('john');
var joe = new Person('joe');
I'm looking to analyze this code and I'm having some trouble. My trouble starts with this line. Customer.prototype = new Person();. Now as far as i'm aware. We can add some methods to our variables like we did with Person.prototype.getName. Great, now Person has a proto pointed towards a function that returns a name. So what does it mean when we do Customer.prototype = new Person();. Does this mean that take all the methods and statements in Person and put them inside the variable Customer?
var Person = function(name) {
this.name = name;
};
Person.prototype.getName = function() {
return this.name;
};
var john = new Person("John");
//Try the getter
alert(john.getName());
Person.prototype.sayMyName = function() {
alert('Hello, my name is ' + this.getName());
};
john.sayMyName();
var Customer = function(name) {
this.name = name;
};
Customer.prototype = new Person();
var myCustomer = new Customer('Dream Inc.');
myCustomer.sayMyName();
Customer.prototype.setAmountDue = function(amountDue) {
this.amountDue = amountDue;
};
Customer.prototype.getAmountDue = function() {
return this.amountDue;
};
myCustomer.setAmountDue(2000);
alert(myCustomer.getAmountDue());
Every object has a prototype, which is also an object.
When you do
Customer.prototype = new Person();
... you set the Customer's prototype object. The methods and properties do not get copied into a Customer object, but when you reference a property/method on a Customer, the prototype chain is followed to find that property/method.
In the case of myCustomer.sayMyName, the JavaScript engine first looks in myCustomer's owned properties, then in its prototype, which is a Person object, and then finally in the prototype of Person which is an object that has that method:
Person.prototype.sayMyName = function() {
alert('Hello, my name is ' + this.getName());
};
By doing Customer.prototype = new Person() we are essentially doing class-inheritance as in another language. So, say we had:
var p = new Person();
Customer.prototype = p;
var c = new Customer();
The prototype (__proto__) of c is p and the prototype of p is Person.prototype.
The naive way to do inheritance would be to Customer.prototype = Person.prototype which would make all instances of Customer share the same methods as Person. But, if we did Customer.prototype.newMethod = ..., it would also modify the prototype of Person.prototype (as they are the same object.
To allow a distinction between Customer prototype and Person prototype, we use new Person() instead as an intermediate in the chain which still has a link to the prototype of Person but is a separate object.
Note: Usually it is more conventional to do Customer.prototype = Object.create(Person) followed by Customer.prototype.constructor = Customer; because doing new Person() means that the constructor of Person is called (which is usually not wanted unless you are actually making a real object).
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/
How do i achieve this :
function Vehicle(){
this.mobility = true;
};
function Car(){};
Car.prototype = new Vehicle();
var myCar = new Car();
console.log(myCar.mobility);
Using objects created with Object literals ?
I know about Object.create() but is there any way like
Car.prototype = new Vehicle();
to achieve that ?
Here's how you do it using __proto__:
var propertiesToInherit = { 'horsepower': 201, 'make': 'Acura' }
var myCar = {};
myCar.__proto__ = propertiesToInherit;
console.log(myCar.horsepower); // 201
console.log(myCar.make); // Acura
That being said, I would avoid doing this. It looks like it is deprecated
One possibility would be Prototype.js; among other things, it allows you to create and extend JS classes using a cleaner syntax:
// properties are directly passed to `create` method
var Person = Class.create({
initialize: function(name) {
this.name = name;
},
say: function(message) {
return this.name + ': ' + message;
}
});
// when subclassing, specify the class you want to inherit from
var Pirate = Class.create(Person, {
// redefine the speak method
say: function($super, message) {
return $super(message) + ', yarr!';
}
});
var john = new Pirate('Long John');
john.say('ahoy matey');
// -> "Long John: ahoy matey, yarr!"
I don't know if I understand your question correctly, but maybe you could try this:
var literal = { mobility: true };
function Car(){};
Car.prototype = literal;
var myCar = new Car();
console.log(myCar.mobility);
Note that if you change the literal, you change all instances of Car that were created.