Sharing a function between different methods of class - javascript

Is there a way to declare a function inside class?
If yes, I'm trying to declare function age() inside the class, but i think it is not possible on JavaScript or maybe I'm wrong.
I do not want to put it outside the class because the code looks more organized like this. What are the options available?
My code is below.
class Animal {
constructor(name) {
this.name = name;
}
cat() {
console.log(`Meow! It is cat and his name is ${this.name}`);
console.log(age('cat'));
}
dog() {
console.log(`Au! It is dog and his name is ${this.name}`);
console.log(age('dog'));
}
function age(animal){
if(animal=='cat') return 7;
if(animal=='dog') return 5;
}
}
const fluffy = new Animal('Fluffy');
fluffy.cat();
const billy = new Animal('billy');
billy.dog();

You've already declared functions inside of the class, just do the same for age. To access it, you need to use this.age since JavaScript doesn't look for class instance variables/functions by default.
class Animal {
constructor(name) {
this.name = name;
}
cat() {
console.log(`Meow! It is cat and his name is ${this.name}`);
console.log(this.age('cat'));
}
dog() {
console.log(`Au! It is dog and his name is ${this.name}`);
console.log(this.age('dog'));
}
age(animal) {
if (animal == 'cat') return 7;
if (animal == 'dog') return 5;
}
}
const fluffy = new Animal('Fluffy');
fluffy.cat();
const billy = new Animal('billy');
billy.dog();

As others already said cat and dog are already functions of Animal (member functions).
If you don't want that the age function is a member function (belongs to an instance of Animal) you can make it static:
class Animal {
constructor(name) {
this.name = name;
}
cat() {
console.log(`Meow! It is cat and his name is ${this.name}`);
console.log(Animal.age('cat'));
}
dog() {
console.log(`Au! It is dog and his name is ${this.name}`);
console.log(Animal.age('dog'));
}
static age(animal){
if(animal=='cat') return 7;
if(animal=='dog') return 5;
}
}
const fluffy = new Animal('Fluffy');
fluffy.cat();
const billy = new Animal('billy');
billy.dog();
If you don't want to make it accessible outside of Animal than make it private:
class Animal {
constructor(name) {
this.name = name;
}
cat() {
console.log(`Meow! It is cat and his name is ${this.name}`);
console.log(Animal.#age('cat'));
}
dog() {
console.log(`Au! It is dog and his name is ${this.name}`);
console.log(Animal.#age('dog'));
}
static #age(animal){
if(animal=='cat') return 7;
if(animal=='dog') return 5;
}
}
const fluffy = new Animal('Fluffy');
fluffy.cat();
const billy = new Animal('billy');
billy.dog();
However having a private static function is rarely useful. The intent of a static method is that it logically belongs to the class but performs a task that does not require an instance of that class.

Hi Jessica You can put it as a method if you want.
But I think anyway in this case you should have a class for cat and another one for dog.
Or pass in the constructor the age but it will mean that the age will not be related to what is the animal.
Long story short you can decide or to create a class for each or to create a method inside the class.

You can create a function in a class, but the correct syntax requires you to omit the 'function' keyword. Also use this keyword to refer to the current object.
class Animal {
constructor(name) {
this.name = name;
}
cat() {
console.log(`Meow! It is cat and his name is ${this.name}`);
console.log(this.age('cat'));
}
dog() {
console.log(`Au! It is dog and his name is ${this.name}`);
console.log(this.age('dog'));
}
age(animal){
if(animal=='cat') return 7;
if(animal=='dog') return 5;
}
}
const fluffy = new Animal('Fluffy');
fluffy.cat();
const billy = new Animal('billy');
billy.dog();

well I can come up with 3 way to define some functionality in a class
number one: method ,it is the common one that you are likely to see in class based codes
class Animal{
//rest of class
age(){
//your function goes here
}
}
you can latter access it with an instance of class
const cat = new Animal() cat.age()
number two: static ,it is somewhat different because it belong to class itself
class Animal{
//rest of class
static age(){
//your function goes here
}
}
in this case you don't need to create an instance of class
Animal.age()
and lastly: treating your function as property it is not different from using method but I would recommend method if you want to use this functionality often there are minor differences in** memory usage**
syntax goes like this
class Animal {
constructor(name) {
this.age= ()=>{//your function}
}}
use age like this
const cat = Animal()
, {age} = cat
age()

Related

Compostion with javascript - no inheritance

I try to use the speak method also to re use with the Zebra class with composition.
SO I have it like this:
class Animal {
constructor(name, age) {
this.name = name;
this.age = age;
}
speak() {
return `my name is: ${this.name} and I am ${this.age} old`;
}
}
class Zebra {
constructor(Animal) {
this.animal = Animal();
}
}
let animal = new Animal("hello", 99);
let zebra = new Zebra();
console.log(zebra.speak());
also composition!!:
class Person {
String Title;
String Name;
Int Age;
public Person(String title, String name, String age) {
this.Title = title;
this.Name = name;
this.Age = age;
}
}
class Employee {
Int Salary;
private Person person;
public Employee(Person p, Int salary) {
this.person = p;
this.Salary = salary;
}
}
Person johnny = new Person ("Mr.", "John", 25);
Employee john = new Employee (johnny, 50000);
I don't recommend to use composition in this case. This is a use-case for inheritance. But academic questions also deserve an answer.
Either use the animal property to call speak:
class Animal {
constructor(name, age) {
this.name = name;
this.age = age;
}
speak() {
return `my name is: ${this.name} and I am ${this.age} old`;
}
}
class Zebra {
constructor(animal) {
this.animal = animal;
}
}
let animal = new Animal("hello", 99);
let zebra = new Zebra(animal);
console.log(zebra.animal.speak());
or add a speak method to Zebra (this is a duplicate of another answer by accident. I didn't see it because it doesn't contain a runnable snippet):
class Animal {
constructor(name, age) {
this.name = name;
this.age = age;
}
speak() {
return `my name is: ${this.name} and I am ${this.age} old`;
}
}
class Zebra {
constructor(animal) {
this.animal = animal;
}
speak() {
return this.animal.speak();
}
}
let animal = new Animal("hello", 99);
let zebra = new Zebra(animal);
console.log(zebra.speak());
This would be more of a thing you are looking for
const animal = {
age: 10,
name: 'hello',
speak() {
return `my name is: ${this.name} and I am ${this.age} old`
}
}
const zebra = {
...animal,
age: 100,
name: 'zebra'
}
console.log(zebra.speak())
This is a simple delegation -
class Zebra {
constructor(animal) {
this.Animal = animal; // animal = Animal
}
speak() {
return this.Animal.speak();
}
}
You can also just use functions instead of new classes -
class Zebra {
constructor(speakFunctionality) {
this.speak = speakFunctionality;
}
}
let zebra = new Zebra((name,age) => { return `my name is: ${this.name} and I am ${this.age} old`; });
zebra.speak();
The first approach doesn't use composition in the best possible way - because when you want to reimplement or add another implementation you'll need to inherit Animal class or provide a type with speak() method.
When doing something like this ask yourself "How do I add a new behavior" - Like you need to implement a Duck how would you do it.
The second approach (With functions) is better because you don't need to provide new classes but create functions - which are easier to manipulate in JS.
This is usually called Strategy pattern where you inject a behavior through ctor or a function.
The example you provided , where you reimplement "Speak" is best suited for Inheritance rather than Composition.
A good example for composition would be a Car with Engine and different parts like Wheels.
class Car {
constructor(engine){
this.Engine = engine;
}
}

Way to test which "sibling class" an object is in Javascript?

Say I have a base class "Pet" and child classes "Dog" and "Cat". Is there a generic way I can take an arbitrary object I know is a "Pet" and test to see if it is "Dog" or "Cat"?
You can either ask the object for its constructor.name property, or if you have a reference to the class, you can use the instanceof operator:
class Pet {
constructor(name) {
this.name = name;
}
}
class Cat extends Pet {
sayHello() { console.log(`${this.name} miaows`) }
}
class Dog extends Pet {
sayHello() { console.log(`${this.name} barks`) }
}
const goofy = new Dog('Pluto');
const garfield = new Cat('Garfield');
console.log(goofy.constructor.name);
console.log(garfield.constructor.name);
console.log(goofy instanceof Dog);
console.log(garfield instanceof Cat);
Please note that Pet shouldn't know about the existence of Dog or Cat (and also neither of the latter two should know anything about the existence of the other).

Why myObject.function() throwing 'is not a function' error? (trying to learn functional instantiation)

I am trying to create a class using a function and giving it some props and a method. If I do the same thing in C# in class-based way and call the mothod this will work fine but in JS it gives me an error. My question is why it behaves in a different way.
code snippet:
function Animal (name) {
let animal = {}
animal.name = name;
animal.eat = function (){
console.log(`${this.name} is eating`)
}
}
let myAnimal = new Animal('dog');
console.log(myAnimal.eat()); //Uncaught TypeError: myAnimal.eat is not a function at proto.js:11
This would be the prototypical way to achieve that in JavaScript:
function Animal(name) {
this.name = name;
}
Animal.prototype.eat = function() {
console.log(`${this.name} is eating`)
}
new Animal('Pooch').eat();
Or with the introduction of classes (since ECMAScript 2015):
class Animal {
constructor(name) {
this.name = name;
}
eat() {
console.log(`${this.name} is eating`)
}
}
new Animal('Pooch').eat();
well if Animal is going to act as a constructor of your sort of class, then you would need to write it like a proper constructor, i.e. drop the let animal = {} bit, and just set properties on this:
function Animal (name) {
this.name = name;
this.eat = function (){
console.log(`${this.name} is eating`)
}
}
let myAnimal = new Animal('dog');
myAnimal.eat();
now this approach has the downside of creating a new function eat() for each instance of Animal instead of binding an existing function eat() to each instance, which is what happens normally with classes. that you can achieve by this:
function Animal (name) {
this.name = name;
}
Animal.prototype.eat = function (){
console.log(`${this.name} is eating`)
}
let myAnimal = new Animal('dog');
myAnimal.eat();
which is actually the proper way people used to define classes in javascript before class was introduced.
however, you can also drop the whole class-like concept, and just have an Animal() function that gives out an object with desired properties:
function Animal (name) {
let animal = {};
animal.name = name;
animal.eat = function (){
console.log(`${this.name} is eating`)
}
return animal;
}
let myAnimal = Animal('dog');
myAnimal.eat();
note how in this approach you have let myAnimal = Animal('dog') instead of let myAnimal = new Animal('dog'), as Animal() is no longer a constructor.
reminder: this is an explanation of how you can instantiate objects with a function, and by no means the recommended way of defining classes in javascript. in older environments, the prototype approach is the recommended way, for newer environments, just use class.
Go with Robby's approach above. For correcting your code, you missed a statement return animal; :)
function Animal (name) {
let animal = {}
animal.name = name;
animal.eat = function (){
console.log(`${this.name} is eating`)
}
return animal;
}
let myAnimal = new Animal('dog');
console.log(myAnimal.eat());

Is there a way to access superclass variables in subclass with JavaScript?

I was learning JavaScript oops with some sample example when I came across to access superclass methods in subclass which is possible with super keyword
but when I try to access or return a variable of super class it returns undefined or the sub class variable I tried in various way to get variable
I have also gone this Stack Overflow post.
class dad {
constructor(name) {
this.name = name;
}
printname() {
console.log(this.name);
var a = 2;
return a;
}
sendVal() {
console.log(this.name);
var a = 2;
return this.name;
}
}
class son extends dad {
constructor(name) {
super(name);
}
printname() {
console.log(super.printname());
}
printvariable() {
console.log(super.name);
}
getvalue() {
console.log(super.sendVal())
}
}
var o1 = new dad('jackson');
var o2 = new son('jack')
o1.printname()
o2.printname()
o2.printvariable()
o2.getvalue()
When you use super.fieldName to access a field of a parent class, you are actually querying the field name on the prototype of the parent class.
So you might believe calling super(name); from the Son constructor sets the name in the prototype of the parent class, but it is not so, it actually sets the name property inherited by the Son class which you can access by using this.name.
So I modified your example code and shown how to actually get a value by calling super.fieldName. In the example I added a property age in the prototype of the Dad class and set its value to 50, now in the Son class printvariable() will correctly call the super.age by referring the prototype of the Dad class.
You can actually see it in action if you use babel to transpile it to ES2015, after all classes in JavaScript are actually syntactic sugar.
class Dad {
constructor(name) {
this.name = name;
Dad.prototype.age = 50; //adding property to prototype
}
printname() {
console.log(this.name);
var a = 2;
return a;
}
sendVal() {
console.log(this.name);
var a = 2;
return this.name;
}
}
class Son extends Dad {
constructor(name) {
super(name);
}
printname() {
console.log(super.printname());
}
printvariable() {
console.log(`super.name will be undefined, as not present in prototype of the Dad class: ${super.name}`);
console.log(`super.age will have a value of 50, present in the prototype of the Dad class: ${super.age}`);
console.log(`this.name will be jack, as it is set from the constructor of the Son class: ${this.name}`);
}
getvalue() {
console.log(super.sendVal());
}
}
var o1 = new Dad('jackson');
var o2 = new Son('jack')
o1.printname();
o2.printname();
o2.printvariable();
o2.getvalue();

How does property lookups after calling super() in subclass actually work

I've a simple example from MDN.
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + ' makes a noise.');
}
}
class Dog extends Animal {
constructor(name) {
super(name); // call the super class constructor and pass in the name parameter
}
speak() {
console.log(this.name + ' barks.');
}
}
let d = new Dog('Mitzie');
d.speak(); // Mitzie barks.
Now, in subclass Dog how does this.name works under the hood. Since this refers to Dog class instance and name is not something which exists on Dog instance. So to access that we use super call which invokes parent's constructor. I get that it looks up.
But can someone please explain via the prototype mechanism (I'm comfortable in understanding the prototype lookup and chaining mechanism).
I'm sure deep down it will boil down to that but not clear about intermediate steps in between. Thanks!
this refers to Dog class
No, this refers to the instantiated object. The instantiated object has an internal prototype of Dog.prototype, and Dog.prototype has an internal prototype of Animal.prototype.
Since this refers directly to the instantiated object (in both constructors, and in all of the methods),
this.name = name;
puts the name property directly on that object, so it's completely fine to reference d.name, or, inside one of the methods, this.name:
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + ' makes a noise.');
}
}
class Dog extends Animal {
constructor(name) {
super(name); // call the super class constructor and pass in the name parameter
}
speak() {
console.log(this.name + ' barks.');
}
}
const d = new Dog('Mitzie');
const dProto = Object.getPrototypeOf(d);
const secondProto = Object.getPrototypeOf(dProto);
console.log(dProto === Dog.prototype);
console.log(secondProto === Animal.prototype);
console.log(d.hasOwnProperty('name'));
Actually, what I wanted to ask was under the hood. So, here's the answer based on #Jai's pointer in comments that I was looking for.
I ran the class based code through es5compiler or any compiler and got this conversion
var Dog = /** #class */ (function (_super) {
__extends(Dog, _super);
function Dog(name) {
return _super.call(this, name) || this;
}
Dog.prototype.speak = function () {
console.log(this.name + ' barks.');
};
return Dog;
}(Animal));
So basically
return _super.call(this, name) inside Dog function explains the confusion of this reference inside speak method of class Dog. It changes the context through call()

Categories

Resources