Prototypes issue in javascript - javascript

i am just starting learn a prototypes in javascript an i can't understand what a problem is in my code. I'm sorry, my question may seem silly
i got an error like this :
Uncaught TypeError: undefined is not a function
why is undefined? I inherited a function of the user.
can't understand it :(
var user = {
sayName: function() {
console.log(this.name)
}
};
user.name = "viktor";
user.sayName();
var user2 = {};
user2.prototype = user;
user2.name = "segey";
user2.sayName();

All you need to set up the prototype chain with plain objects is:
var user2 = Object.create(user); // set `user` as prototype of `user2`
user2.name = "segey";
user2.sayName();

For you question correct solution will:
function User() {
this.name = 'Viktor';
return this;
}
User.prototype = Object.create({
sayName: function() {
return this.name;
}
});
function User2() {}
User2.prototype = Object.create(User.prototype);
var user = new User();
user.sayName(); // 'Viktor'
user2 = new User2();
user2.name = 'Bogdan';
user2.sayName(); // 'Bogdan'
And detailed explanation with example.
Let say we have some basic class Animal. Our Animal have age and name.
function Animal() {
this.age = 5;
this.name = "Stuffy";
return this;
}
Animal.prototype = Object.create({
getAge: function() {
return this.age;
},
getName: function() {
return this.name;
}
});
And when I spent some time with architecture I understand that I also need SubClass of Animal. For example, let it will be Dog class with new property and functions. And also Dog must extend functions and properties from Animal class.
function Dog() {
Animal.apply(this, arguments); // Call parent constructor
this.wantsEat = true; // Add new properties
return this;
}
Dog.prototype = Object.create(Animal.prototype); // Create object with Animal prototype
Object.extend(Dog.prototype, { // Any extend() function, wish you want
constructor: Dog, // Restore constructor for Dog class
eat: function() {
this.wantsEat = false;
return this;
}
});
Or you can use Object.defineProperties() and extend in this way:
Dog.prototype = Object.create(Animal.prototype, {
constructor: {
value: Dog
},
eat: {
value: function() {
this.wantsEat = false;
return this;
}
}
});

Related

How to use object oriented without using keyword ('new')

What am I trying to do is as following:
var Person = function(name) {
this.name = name;
}
Person.prototype.getName = function () {
return this.name;
}
// This will return error;
console.log(Person('John').getName());
// While this won't.
var p1 = new Person('john');
console.log(p1.getName());
Am I misunderstanding something?
// This will return error;
console.log(Person('John').getName());
it returns an error bcoz Person() by default returns undefined ,but if you use new it will return the newly created object.
// While this won't.
var p1 = new Person('john');
console.log(p1.getName());
this works bcoz a new object with __proto__ set to Person.prototype is returned and since there is a getName() on it , it works as expected.
you may use scope safe constructor for your constructor to work without explicit new.
function Person(name) {
if(this instanceof Person) {
this.name = name;
} else {
return new Person(name);
}
}
http://www.mikepackdev.com/blog_posts/9-new-scope-safe-constructors-in-oo-javascript
If you don't want to have the new keyword all over your code (and I can't think of a good reason to want that, you would be basically hiding an important information), you could just do something like:
var pPerson = function(name) {
this.name = name;
};
pPerson.prototype.getName = function () {
return this.name;
};
var Person = function (name) {
return new pPerson(name);
};
You can use Object.create() if you don't want to use the new keyword. Here's an example from MDN:
// Animal properties and method encapsulation
var Animal = {
type: "Invertebrates", // Default value of properties
displayType : function(){ // Method which will display type of Animal
console.log(this.type);
}
}
// Create new animal type called animal1
var animal1 = Object.create(Animal);
animal1.displayType(); // Output:Invertebrates
// Create new animal type called Fishes
var fish = Object.create(Animal);
fish.type = "Fishes";
fish.displayType(); // Output:Fishes
If you really really hate your self, you can do this
var Person = function(name) {
var This = {};
This.name = name;
//See note
Object.setPrototypeOf(This, arguments.callee.prototype);
return This;
}
Person.prototype.getName = function () {
return this.name;
}
var p = Person('John');
console.log(p.getName());
Note
You absolutely have to read about this.
You can try creating prototype functions as a part of parent function itself.
var Person = function(name) {
this.name = name;
this.get_name = function() {
return this.name;
}
return this;
}
Person.prototype.getName = function() {
return this.name;
}
// This will return error;
console.log(Person('John').get_name());
// While this won't.
var p1 = new Person('john');
console.log(p1.getName());

javascript prototypical inheritance confusion

Below is a working example to show how the prototype of Javascript work. So from my understand is simply the customer instance inherited the prototype function of the Person.
var Person = function (name) {
this.name = name;
};
Person.prototype.getName = function () {
return this.name;
};
var john = new Person("John");
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());
But one thing bug me is that why the author do a getAmountdue prototype function? it simply return this.amountDue.
I think the issue is not related to javascript prototypical inheritance.
To wrap the property into a function return could abstract the implementation.
For example, if your boss want you provide a decorated result of this.amountDue, you can just change the implementation of getAmountDue method.

Inherited class not getting its own methods in Javascript

function Mammal(name){
this.name = name;
}
Mammal.prototype.displayName = function(){
return this.name;
}
function Organism(name){
this.orgName = name;
}
Organism.prototype.print = function(){
return this.orgName;
}
Organism.prototype = new Mammal(); //Organism inherits Mammal
//Testing
var o = new Organism('Human');
o.print()
This comes as undefined. Why? this should show since it is a method of class Organism.
print() does not show up in the object
When you do:
Organism.prototype = new Mammal(); //Organism inherits Mammal
you replace the entire prototype object, thus wiping out the previously assigned:
Organism.prototype.print = function(){
return this.orgName;
}
You can fix it by changing the order so you "add" your new method to the inherited prototype:
function Organism(name){
this.orgName = name;
}
Organism.prototype = new Mammal(); //Organism inherits Mammal
Organism.prototype.print = function(){
return this.orgName;
}
FYI as an aside, you should be thinking about using Organism.prototype = Object.create(Mammal.prototype); instead and you should be calling the constructor of the base object too. See here on MDN for examples.
When you assign
Organism.prototype = new Mammal();
you are clobbering the Organism.prototype object that had the print function on it. Try this instead for your inheritance:
function Mammal(name){
this.name = name;
}
Mammal.prototype.displayName = function(){
return this.name;
}
function Organism(name){
this.orgName = name;
}
Organism.prototype = Object.create(Mammal.prototype);
Organism.constructor = Mammal;
// or _.extend(), if using underscore
jQuery.extend(Organism.prototype, {
print: function(){
return this.orgName;
}
});
//Testing
var o = new Organism('Human');
o.print()

Passing arguments to anonymous function of module

$(document).ready(function () {
var patient = (function (options) {
var age = options.age;
var name = options.name;
function getName() {
return this.name;
}
function setName(val) {
name = val;
}
function getAge() {
return this.age;
}
function setAge(val) {
age = val;
}
return {
getAge: getAge,
setAge: setAge,
getName: getName,
setName: setName
}
})();
});
I realize that I'm never passing any options in my example here.
If I try to do something like patient.setAge('100') and then console.log(patient.getAge()) I get an error saying cannot read property Age of undefined. The overarching theme that I'm trying to get at is within a module, how can I emulate consturctors to instantiate a new patient object while keeping all the OOP goodness of private variables and all that jazz.
I've seen some examples of constructors in a module pattern on here and I haven't understood them very well. Is it a good idea in general to have a constructor in a module? Is its main purpose similarity with class-based languages?
This is a constructor:
function Patient(options) {
options = options || {};
this.age = options.age;
this.name = options.name;
}
$(document).ready(function () {
var patient = new Patient();
});
You can put it inside a module if you want. What you shouldn’t do is provide getters and setters, especially ones that don’t do anything. If you’re exposing a variable through two properties to get and set it, it should just be one property.
Try this
function Patient (options) {
options = options || {};
var age = options.age;
var name = options.name;
function getName() {
return name;
}
function setName(val) {
name = val;
}
function getAge() {
return age;
}
function setAge(val) {
age = val;
}
return {
getAge: getAge,
setAge: setAge,
getName: getName,
setName: setName
}
}); // pass empty object
$(document).ready(function () {
var p1 = new Patient({});
var p2 = new Patient();
var p3 = new Patient({age:20});
var p4 = new Patient({name:"abcd"});
var p5 = new Patient({age:21, name:"abcd"});
});

how to use prototype to avoid copying of functions in javascript?

I had written this code to simulate OOP inheritance and calling baseclass in javascript and it works:
function Animal(name,age)
{
this._name = name;
this.setName = function (name) { this._name = name }
this.getName = function() { return this._name }
}
function Cat(name,age)
{
Animal.call(this,name,age); // call baseclass constructor
this.getName = function() { return Cat.prototype.getName.call(this)+", a cat" }
}
Cat.prototype = new Animal(); // will create the baseclass structure
/// ***** actual execution *****
var puss = new Cat("Puss",3);
var cheshire = new Cat("Cheshire",10);
// do some actions
console.log ( puss.getName() );
// change cat's name
puss.setName("Puss in boots");
alert ( "new name -->"+puss.getName() );
problem is that, for each instance of "new Cat()" the "getName" and "setName" functions are replicated.
I have read a lot of articles on prototyping but none addressed the issue of calling the baseclass function.
You should assign the methods to the prototype of the function, for example,
function Animal(name, age) {
this._name = name;
this._age = age;
}
Animal.prototype.getName = function () { return this._name; }
Animal.prototype.setName = function (value) { this._name = value; }
function Cat(name, age) {
Animal.call(this, name, age);
}
Cat.prototype = new Animal();
Cat.prototype.getName = function () {
return Animal.prototype.getName.call(this) + ", a cat";
}
Are you looking for __proto__ which stores prototype data?
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/Proto
If you do a console.log(puss.__proto__.getName) you'll get what seems to be the "baseclass" function but I'm not sure how cross-browser is this.
From http://phrogz.net/js/classes/OOPinJS2.html
Javascript does not have any sort of 'super' property, which would
point to its parent class. Instead, you use the call() method of a
Function object, which allows you to run a function using a different
object as context for it. If you needed to pass parameters to this
function, they would go after the 'this'.
In your case it works the same for functions as "methods", so you can do:
Animal.prototype.setName.call(this, name);

Categories