When I try to call the method( getdetails() method of Teacher ) of child constructor function the parent constructor method is being called . Isn't the child method supposed to shadow the parent method . How to call the child constructor method getDetails()?
let Person = function() { };
Person.prototype.personName = "Smith";
Person.prototype.age = 37;
Person.prototype.getDetails = function() {
return `Person Name: ${this.personName}. Age is ${this.age}`;
};
let Teacher = function() { };
Teacher.prototype.mainSubject = "Physics";
Teacher.prototype.getDetails = function() {
return `Main subject is ${this.mainSubject}`;
};
Teacher.prototype = Object.create(Person.prototype); // inheritance
let teacher1 = new Teacher();
console.log(teacher1.getDetails());
You assign a new object to Teacher.prototype therefore losing everything you assigned to it beforehand. You should create the object before everything else.
let Person = function() { };
Person.prototype.personName = "Smith";
Person.prototype.age = 37;
Person.prototype.getDetails = function() {
return `Person Name: ${this.personName}. Age is ${this.age}`;
};
let Teacher = function() { };
Teacher.prototype = Object.create(Person.prototype); // inheritance
Teacher.prototype.mainSubject = "Physics";
Teacher.prototype.getDetails = function() {
return `Main subject is ${this.mainSubject}`;
};
let teacher1 = new Teacher();
console.log(teacher1.getDetails());
But nowadays you could also use classes instead of functions.
class Person {
personName = "Smith";
age = 37;
getDetails() {
return `Person Name: ${this.personName}. Age is ${this.age}`;
}
}
class Teacher extends Person {
mainSubject = "Physics";
getDetails() {
return `Main subject is ${this.mainSubject}`;
}
}
let teacher1 = new Teacher();
console.log(teacher1.getDetails());
Related
I am trying to learn classes and setters and getters in JavaScript .. but my code isn't working .. it alerts undefined .. here is my code
function Person () {
name:"something"
Person.prototype = {
get Name (){
return name;
},
set Name (val){
this.name = val;
}
};
};
var person = new Person();
alert(person.name);
This is the right way to set getters and setters in your example:
function Person () {
this.name = "something";
}
Person.prototype = {
get Name() {
return this.name;
},
set Name(val) {
this.name = val;
}
};
var person = new Person();
person.Name = 'example';
alert(person.name);
JS is based on prototypes, then u can define propertys:
function Person(){
this._name = '';
}
Object.defineProperty(Person.prototype, "name", {
get: function(){
return this._name;
},
set: function(value){
this._name= value;
},
enumerable:true,
configurable: true
});
Then u can set or get property "name"
var p = new Person()
p.name = 'Stackoverflow'
alert(p.name) // Stackoverflow
In ES6 u can use the keyword class, example:
class Person {
constructor() {
this.name = '';
}
}
I'm working on making performance updates on my javascript code.
In Firefox I got this warning:
mutating the [[Prototype]] of an object will cause your code to run very slowly; instead create the object with the correct initial [[Prototype]] value using Object.create
I wrote some scripts to prove this, and the results are great: without mutation a simple script runs 66% faster.
But I have trouble converting my code without mutation, I can't write the getters:
This is what I have now:
// Class
function FooBar(options) {
this.options = options;
}
// Prototype
FooBar.prototype = {
// Getters
get a() {
return this.options.a;
},
get b() {
return this.options.b;
},
get ab() {
return this.options.a + this.options.b;
},
// Methods
displayOptions: function() {
console.log(this.options);
}
};
// Code
var options = {
a: 'foo',
b: 'bar'
};
var fooBar = new FooBar(options);
console.log(fooBar.a);
console.log(fooBar.b);
console.log(fooBar.ab);
fooBar.displayOptions();
The getters as a prototype using the this keyword in their return are the problem.
If I use Object.defineProperty the this keyword is wrong, unless I do it inside the constructor, but it would recreate the property on each instance of the class and slow my code down even further.
This works (I just messed up the syntax in my previous attempt):
// Class
function FooBar (options) {
this.options = options;
}
//Prototype getters
Object.defineProperty(FooBar.prototype, 'a', {
get: function() {
return this.options.a;
}
});
Object.defineProperty(FooBar.prototype, 'b', {
get: function() {
return this.options.b;
}
});
Object.defineProperty(FooBar.prototype, 'ab', {
get: function() {
return this.options.a + this.options.b;
}
});
// Methods
FooBar.prototype.displayOptions = function() {
console.log(this.options);
};
// Code
var options = {
a:'foo',
b:'bar'
};
var fooBar = new FooBar (options);
console.log(fooBar.a);
console.log(fooBar.b);
console.log(fooBar.ab);
fooBar.displayOptions();
For those who are curious about the benefits of converting scripts like this to run faster: Run following code and look to your output in the console (Chrome - 66% faster, Firefox - no difference (curious, since I got the warning from Firefox)):
// WITHOUT PROTOTYPING
var Person1 = function() {
this.name = 'myName';
this.changeName = function(name) {
this.name = name;
};
this.changeName2 = function(name) {
this.name = name;
};
this.changeName3 = function(name) {
this.name = name;
};
this.changeName4 = function(name) {
this.name = name;
};
}
// WITH PROTOTYPING, WITH MUTATION
var Person2 = function() {
this.name = 'myName';
}
Person2.prototype = {
changeName: function(name) {
this.name = name;
},
changeName2: function(name) {
this.name = name;
},
changeName3: function(name) {
this.name = name;
},
changeName4: function(name) {
this.name = name;
}
};
// WITH PROTOTYPING, WITHOUT MUTATION
var Person3 = function() {
this.name = 'myName';
}
Person3.prototype.changeName = function(name) {
this.name = name;
};
Person3.prototype.changeName2 = function(name) {
this.name = name;
};
Person3.prototype.changeName3 = function(name) {
this.name = name;
};
Person3.prototype.changeName4 = function(name) {
this.name = name;
};
// DO THE TEST
var i=0, len=1000000;
// TEST1
window.performance.mark('mark_test_start');
for(i=0;i<len;i++) {
p = new Person1();
p.changeName('myName2');
}
window.performance.mark('mark_test_end');
window.performance.measure('no-prototyping', 'mark_test_start', 'mark_test_end');
// TEST2
window.performance.mark('mark_test2_start');
for(i=0;i<len;i++) {
p = new Person2();
p.changeName('myName2');
}
window.performance.mark('mark_test2_end');
window.performance.measure('prototyping-with-mutation', 'mark_test2_start', 'mark_test2_end');
// TEST3
window.performance.mark('mark_test3_start');
for(i=0;i<len;i++) {
p = new Person2();
p.changeName('myName2');
}
window.performance.mark('mark_test3_end');
window.performance.measure('prototyping-without-mutation', 'mark_test3_start', 'mark_test3_end');
// OUTPUT tests
var items = window.performance.getEntriesByType('measure');
for (var i = 0; i < items.length; ++i) {
var req = items[i];
console.log(req.name + ': ' + req.duration.toFixed(2));
}
I am trying to mock inheritance in Javascript using prototype.
I have a function named Model and a type of model => Item.
var Model = function() {
this.names = ["name1", "name2"];
}
Model.prototype.Item = function(args) {
this.init = function(item_name) {
this.names[0] = item_name; // ERROR: Cannot set property '0' of undefined
}
}
var m = new Model();
var i = new m.Item();
i.init("New Name"); // ERROR: Cannot set property '0' of undefined
How can I access names array from init() function above?
Inheritance in Javascript is tricky! Read this post for a great explanation of traditional object oriented inheritance in Javascript: http://blog.slaks.net/2013-09-03/traditional-inheritance-in-javascript/.
var Model = function () {
this.names = ["name1", "name2"];
};
var Item = function () {
//When inheriting in Javascript you must
//call the inherited function's constructor manually.
Model.call(this);
};
//Inherit Model's prototype so you get all of Model's methods.
Item.prototype = Object.create(Model.prototype);
Item.prototype.constructor = Item;
Item.prototype.init = function (item_name) {
this.names[0] = item_name;
};
var Employee = function () {
Model.call(this);
};
Employee.prototype = Object.create(Model.prototype);
Employee.prototype.constructor = Employee;
var myItem = new Item();
myItem.init("New Name");
//prints New Name, name2
console.log(myItem.names);
var myEmployee = new Employee();
//prints name1, name2
console.log(myEmployee.names);
Analogous code in a more traditional object oriented language (C#):
public class Model
{
public Model()
{
this.Names = new[] {"name1", "name2"};
}
public string[] Names { get; set; }
}
public class Item : Model
{
public Item() : base() { }
public void init(string item_name)
{
this.Names[0] = item_name;
}
}
public class Employee : Model
{
public Employee() : base() { }
}
var myItem = new Item();
myItem.init("New Name");
//prints New Name, name2
Console.WriteLine(String.Join(",", myItem.Names));
var myEmployee = new Employee();
//prints name1, name2
Console.WriteLine(String.Join(",", myEmployee.Names));
The issue you're having is that in the second item Item, your reference to this has no idea about it's "parent" object Model.
One way to re-write this is like so:
var Model = function() {
this.names = ["name1", "name2"];
}
Model.prototype.init = function(item_name) {
this.names[0] = item_name;
}
var Item = new Model();
Item.init("New Name");
console.log(i);
Fiddle here: http://jsfiddle.net/BksS3/1/
As far as making this work is concerned, this would work too.
var Model = function() {
this.names = ["name1", "name2"];
}
Model.prototype.Item = function(args) {
this.init = function(item_name) {
this.names[0] = item_name;
}
}
var m = new Model();
var i = new m.Item();
i.init.apply(m,["New Name"]);
Manager class object will access all method from Person and Employee.
Multilevel Inheritance example
function Person(firstName,lastName,marks,age,gender)
{
this.firstName = firstName;
this.lastName = lastName;
this.age=age;
this.gender=gender;
}
Person.prototype.getFullname = function()
{
console.log("Full Name is "+this.firstName +' '+this.lastName);
}
function Employee(firstName,lastName, marks, rollno, salary)
{
Person.call(this,firstName,lastName,marks, rollno, salary);
this.rollno = rollno;
this.salary=salary;
}
function Manager(firstName,lastName, marks, rollno, salary, code) {
Employee.call(this, firstName,lastName,marks, rollno, salary, code);
this.code = code;
}
Employee.prototype = Object.create(Person.prototype);
Employee.prototype.constructor = Employee;
Employee.prototype.getSalary = function()
{
console.log(`Salary of ${this.firstName} ${this.lastName} is ${this.salary}`);
}
Manager.prototype = Object.create(Employee.prototype);
Manager.prototype.constructor = Manager;
Manager.prototype.designation = function() {
console.log("You'r designation is Manager");
}
var m = new Manager("shankar","singh", 21,100, 40000,"CS12");
console.log(m);
m.getFullname();
m.getSalary();
m.designation();
</script>
This is how you implement multi-level inheritance in JavaScript.
<script>
//Multi Level Inheritance Example
//Parent Class
class A{
constructor()
{
this.a=0;
}
setA()
{
this.a=10;
}
}
//Child Class
class B extends A{
constructor()
{
super();//call parent class constructor
this.b=0;
}
setB()
{
this.b=20;
}
}
class Addition extends B{
add()
{
this.setA();
this.setB();
return this.a+this.b;
}
}
class Print extends Addition{
print()
{
var result=this.add();
document.write("<br/>a="+this.a);
document.write("<br/>b="+this.b);
document.write("<br/>Addition="+result);
}
}
//Make Object
let obj=new Print();
obj.print();
/*
Assignment:
Make subtraction, multiplication, diuvision classes and print the output as
==============
Two Digit Calculator
==============
a=10
b=20;
Addition=30
Subtraction=-10
Multiplication=200
Division:.5
*/
</script>
I'm trying to make it possible to inherit from this class:
function Vehicle(p) {
this.brand = p.brand || "";
this.model = p.model || "";
this.wheels = p.wheels || 0;
}
Vehicle.prototype.getBrand = function () {
return this.brand;
};
Vehicle.prototype.getModel = function () {
return this.model;
};
Vehicle.prototype.getWheels = function () {
return this.wheels;
};
var myVehicle = new Vehicle({
brand: "Mazda",
model: "RX7",
wheels: 4
});
console.log(myVehicle);
I tried doing it this way:
function Vehicle(p) {
this.brand = p.brand || "";
this.model = p.model || "";
this.wheels = p.wheels || 0;
}
Vehicle.prototype.getBrand = function () {
return this.brand;
};
Vehicle.prototype.getModel = function () {
return this.model;
};
Vehicle.prototype.getWheels = function () {
return this.wheels;
};
function Car (){}
Car.prototype = new Vehicle();
Car.prototype.getWheels = function() {
return 4;
};
var myCar = new Car({
brand: "Mazda",
model: "RX7"
});
console.log(myCar);
but it seems like it doesn't work:
> Uncaught TypeError: Cannot read property 'brand' of undefined
Could someone explain to me what's wrong? I guess it's not the write way to implement it but why?
In addition to what #elclanrs said:
function Car () {
Vehicle.apply(this, arguments);
}
var c = function() {};
c.prototype = Vehicle.prototype;
Car.prototype = new c();
Live demo: http://jsfiddle.net/x3K9b/1/
You need to call "super" in Car:
function Car() {
Vehicle.apply(this, arguments);
}
Aside from that you could make p optional by just assigning an empty object for example; that would get rid of the error. And finally point to the right constructor so:
function Vehicle(p) {
p = p || {}; //<=
this.brand = p.brand || "";
this.model = p.model || "";
this.wheels = p.wheels || 0;
}
//...
Car.prototype = new Vehicle();
Car.prototype.constructor = Car; //<=
Edit: Otherwise just use Object.create:
Car.prototype = Object.create(Vehicle.prototype);
That takes care of assigning the constructor and everything.
I have a Constructor function "Animals", that is namespacing some other Constructor functions, "Crocodile" and "Monkey":
var Monkey = function(Animals) {
this.Animals = Animals;
};
Monkey.prototype.feedMe = function() {
this.Animals.feed();
};
var Crocodile = function(Animals) {
this.Animals = Animals;
};
Crocodile.prototype.feedMe = function() {
this.Animals.feed();
};
var Animals = function(zoo) {
this.zoo = zoo;
};
Animals.prototype.feed = function() {
//feed the animal
};
Animals.prototype.Monkey = function() {
this.Animals = Animals.prototype;
};
Animals.prototype.Monkey.prototype = Monkey.prototype;
Animals.prototype.Crocodile = function() {
this.Animals = Animals.prototype;
};
Animals.prototype.Crocodile.prototype = Crocodile.prototype;
With the intention that I should be able to do the following:
var animals = new Animals("NY");
var monkey = new animals.Monkey();
monkey.feed();
I'm receiving an error that says that monkey.feed() is not a function. I'm assuming i'm doing something wrong with the way i'm inheriting the Monkey function inside the Animal constructor function but for the life of me I haven't been able to find the solution.
What is the correct method I should be using to namespace these functions?
I have seen quite some stuff, but abusing prototypes for namespaces, what the heck. What's wrong with a nice and simple:
var Animals = {
Crocodile: {
}
}
Or if you want the constructor way:
var Animals = function () {
return {
Crocodile: function () {}
}
};
var a = new Animals();
var c = new a.Crocodile();