I have to have two arguements, name and dept, and made a name and dept instance variable that defaults to name unknown and department unknown, then make the get and set methods for them, but each time I run this it gives me the class name and dept is undefined
Well originally I didn't have it in a class and had it as a straight const function, and it was working, but when I couldn't reference it properly in another file, I was told they need to be put in a class which I tried, and now its not giving the output I need.
class Faculty {
constructor(name, dept) {
this.name = "name unknown";
this.dept = "department unknown";
}
getName() {
return this.name;
}
getDept() {
return this.dept;
}
setName(name) {
this.name = name;
}
setDept(dept) {
this.dept = dept;
}
}
Faculty.toString = function () {
return this.name.concat(" of ").concat(this.dept);
}
//Faculty.name = "Testname";
//Faculty.dept = "Electronic Technology";
console.log(Faculty.toString());
When ran it gives Faculty of undefined, even when I try to define name, it still just says Faculty, though I need it to be of that defaults to name unknown of department unknown unless set otherwise.
Here's how I would put it (and it works)
EDIT : Since this answer was chosen, I will add here the good elements pointed by the other answers
const DEFAULT_NAME = "name unknown";
const DEFAULT_DEPT = "department unknown";
class Faculty {
constructor(name = DEFAULT_NAME, dept DEFAULT_DEPT) {
this.name = name;
this.dept = dept;
}
getName() {
return this.name;
}
getDept() {
return this.dept;
}
setName(name) {
this.name = name;
}
setDept(dept) {
this.dept = dept;
}
toString() {
return `${this.name} of ${this.dept}`;
}
}
const f = new Faculty("Faculty", "Department");
console.log(f.toString());
Also you can use the default params like this :
class Faculty {
constructor(name = 'name unknown', dept = 'department unknown') {
this.name = name;
this.dept = dept;
}
getName() {
return this.name;
}
getDept() {
return this.dept;
}
setName(name) {
this.name = name;
}
setDept(dept) {
this.dept = dept;
}
toString() {
return `${this.name} of ${this.dept}`;
}
}
const f = new Faculty('Alex', 'Maths');
console.log(f.toString());
For one, you'd have to create a new instance of Faculty in order to call one of its class methods.
Second, there's no need to declare the toString method outside of the class; it can be included just as the others.
Third, I think the method itself could be simplified/clarified by using template literals.
const DEFAULT_NAME = "name_unknown";
const DEFAULT_DEPARTMENT = "department_unknown";
class Faculty {
constructor(name, dept) {
this.name = name || DEFAULT_NAME;
this.dept = dept || DEFAULT_DEPARTMENT;
}
getName() {
return this.name;
}
getDept() {
return this.dept;
}
setName(name) {
this.name = name;
}
setDept(dept) {
this.dept = dept;
}
toString() {
return `${this.name} of ${this.dept}`
}
}
//With name and department
const faculty = new Faculty("John Smith", "Department XYZ");
console.log(faculty.toString());
//Without name and department
const faculty_default = new Faculty();
console.log(faculty_default.toString());
Related
Good Evening.
I want to create a parent class vehicle with a private member #manufacturer. I want to extend class vehicle to class car and motorcycle. I declared a const d = new car. If i try to acces to manufacturer by console.log(d.manufacturer) i recive and undefined.
// task 1
class vehicle {
#manufacturer;
name;
constructor(manufacturer, name) {
this.#manufacturer = manufacturer;
this.name = name;
}
get name() {
return this.name;
}
}
class car extends vehicle {
#type;
constructor(manufacturer, name, type) {
super(manufacturer, name);
this.#type = type;
}
get type() {
return this.#type;
}
set type(value) {
if (value.length > 3) this.#type = value;
}
}
class motorcycle extends vehicle {
motortype;
constructor(manufacturer, name, motortype) {
super(manufacturer, name);
this.motortype = motortype;
}
get motortype() {
return this.motortype;
}
set motortype(value) {
if (value.length > 3) {
this.motortype = value;
}
}
}
const e = new motorcycle('audi', 'a3', 'sport');
console.log(e.motortype);
e.motortype = 'supersport';
console.log(e.motortype);
const d = new car('bmw', 'm2', 'cool');
console.log(d.type);
d.type = 'lazy';
console.log(d.type);
console.log(e.name);
console.log(e.motortype);
console.log(d.manufacturer)
I tried to change the constructor in order to fix this problem by putting as well an #manufacturer in the constructor. But i recive an error.
Private properties aren't inherited thus with a car object (subclass) you can't access a private member defined in vehicle (superclass). But you can make the private member accessibile with a public get method like this:
class vehicle {
#manufacturer;
name;
constructor(manufacturer, name) {
this.#manufacturer = manufacturer;
this.name = name;
}
get name() {
return this.name;
}
get manufacturer(){
return this.#manufacturer;
}
}
class car extends vehicle {
#type;
constructor(manufacturer, name, type) {
super(manufacturer, name);
this.#type = type;
}
get type() {
return this.#type;
}
set type(value) {
if (value.length > 3) this.#type = value;
}
}
class motorcycle extends vehicle {
motortype;
constructor(manufacturer, name, motortype) {
super(manufacturer, name);
this.motortype = motortype;
}
get motortype() {
return this.motortype;
}
set motortype(value) {
if (value.length > 3) {
this.motortype = value;
}
}
}
const e = new motorcycle('audi', 'a3', 'sport');
console.log(e.motortype);
e.motortype = 'supersport';
console.log(e.motortype);
const d = new car('bmw', 'm2', 'cool');
console.log(d.type);
d.type = 'lazy';
console.log(d.type);
console.log(e.name);
console.log(e.motortype);
console.log(d.manufacturer)
sorry, the incrementAge function is returning undefined/NaN when invoked after defining the new User. I am not sure what's wrong
function User(name,age){
this.name = name;
this.age = age;
}
User.prototype.incrementAge = ()=>{
return this.age++;
}
const mike = new User("Mike",20);
console.log(mike.incrementAge());
The correct way to do this is to create a User class and create a method to raise the value of the variable age.
As you can see by calling the increment age method several times the value is added.
class User {
constructor(name, age) {
this.name = name;
this.age = age;
}
incrementAge() {
return ++this.age;
}
}
const mike = new User("Mike", 20);
console.log(mike.incrementAge());
console.log(mike.incrementAge());
The solution (by #ChrisG in comments)
function User(name, age) {
this.name = name;
this.age = age;
}
User.prototype.incrementAge = function () {
return ++this.age;
}
const mike = new User("Mike", 20);
console.log(mike.incrementAge());
I am running this simple class in JavaScript but in console it give me a "Maximum call stack size exceeded" error. and help?!?
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
get name() {
return String(this.name);
}
get age() {
return String(this.age);
}
set name(name) {
this.name = name;
}
set age(age) {
this.age = age;
}
}
let p1 = new Person('Ehsan', 23);
this is a screen shot of the console
}
If you want to indicate that the age property should not be directly used, you should use a different property name than the name used by setters and getters. If the property that the setter / getter sets or gets is the same name as the setter or getter, it'll just keep calling itself, resulting in your error.
A common convention is to put an underscore before the property:
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
get name() {
return String(this._name);
}
get age() {
return String(this._age);
}
set name(name) {
this._name = name;
}
set age(age) {
this._age = age;
}
}
let p1 = new Person('Ehsan', 23);
console.log(p1.age);
p1.age = 32;
console.log(p1.age);
But the property is still viewable by consumers via p1._age - if you wanted to prevent that, you can make it more private with a closure and WeakMap:
const Person = (() => {
const privateVals = new WeakMap();
return class Person {
constructor(name, age) {
const privateObj = {};
privateObj.name = name;
privateObj.age = age;
privateVals.set(this, privateObj);
}
get name() {
return String(privateVals.get(this).name);
}
get age() {
return String(privateVals.get(this).age);
}
set name(name) {
privateVals.get(this).name = name;
}
set age(age) {
privateVals.get(this).age = age;
}
}
})();
let p1 = new Person('Ehsan', 23);
console.log(p1.age);
p1.age = 32;
console.log(p1.age);
You can't have a getter / setter pair and a field with the same name. this.name = inside the setter will itself call the setter. If you really need a getter / setter, use another field, e.g. this._name = ... But to be honest: Don't use a getter / setter here. If you do person.name = 15 you should rather fix that than trying to do that with getters / setters.
I believe you just have to rename your class variables in your constructor and then you should be good to go?
class Person {
constructor(name, age) {
this._name = name;
this._age = age;
}
get name() {
return String(this._name);
}
get age() {
return String(this._age);
}
set name(name) {
this._name = name;
}
set age(age) {
this._age = age;
}
}
I'm trying to use the revealing module pattern with inheritance. I seem to have it working fine, but it uses "__proto__", which I understand it's considered deprecated. Is there a better was to create the inheritance with out using "__proto__"?
var Person = (function() {
var _name;
var api = {
init: init,
getName: getName
}
return api;
function init(name) {
_name = name;
}
function getName() {
return _name;
}
}())
var Teacher = (function() {
var _subject = "Math";
var api = {
getSubject: getSubject,
say: say
}
api.__proto__ = Person;
return api;
function getSubject() {
return _subject;
}
function say() {
console.log("I am " + this.getName() + " and I teach " + _subject)
}
}());
Teacher.init("Bob");
Teacher.say() // I am Bob and I teach math
https://plnkr.co/edit/XbGx38oCyvRn79xnn2FR?p=preview
The direct equivalent – setting the prototype, still a bad idea – is Object.setPrototypeOf:
Object.setPrototypeOf(api, Person);
The normal way of creating an object based on a prototype with Object.create and then adding properties to it works fine here, though:
var api = Object.create(Person);
api.getSubject = getSubject;
api.say = say;
but ideally you would just use constructors:
class Person {
constructor(name) {
this._name = name;
}
getName() {
return this._name;
}
}
class Teacher extends Person {
constructor(name) {
super(name);
this._subject = 'Math';
}
getSubject() {
return this._subject;
}
say() {
console.log(`I am ${this.getName()} and I teach ${this.getSubject()}`);
}
}
var teacher = new Teacher('Bob');
teacher.say() // I am Bob and I teach math
without ES6:
function Person(name) {
this._name = name;
}
Person.prototype.getName = function () {
return this._name;
};
function Teacher(name) {
Person.call(this, name);
this._subject = 'Math';
}
Teacher.prototype = Object.create(Person.prototype);
Teacher.prototype.getSubject = function () {
return this._subject;
};
Teacher.prototype.say = function () {
console.log('I am ' + this.getName() + ' and I teach ' + this.getSubject());
};
var teacher = new Teacher('Bob');
teacher.say(); // I am Bob and I teach math
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>