Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do classes and functions behave differently in Javascript?

My understanding was that all classes were essentially functions, and all instances were essentially objects. But something confused me.

//Take this for example:

    function AnimalFunc(name) {
        this.name = name;
        this.sayName = function() {
            console.log(this.name);
        }
    }

//And compare it with this:

    class AnimalClass {
        constructor(name) {
            this.name = name;
        }
        
        sayName() {
            console.log(this.name);
        }
    }

//Now I instantiate them.

    cat = new AnimalFunc("cat")
    cat.sayName() // -> "cat"
    dog = new AnimalClass("dog")
    dog.sayName() // -> "dog"
    
    console.log(Object.keys(cat));
    console.log(Object.keys(dog));

Expected Observations:

  1. typeof(AnimalClass) and typeof(AnimalFunc) both return function.
  2. typeof(cat) and typeof(dog) both return object.

Unexpected Observations:

  1. If I do Object.keys(cat), I get ["name","sayname"].
  2. But if I do Object.keys(dog), I get ["name"].

My question is: why do I not get sayname as a key for the class instance? Why do I get it only for the function instance?

like image 705
happy_sisyphus Avatar asked Jan 28 '23 08:01

happy_sisyphus


2 Answers

The first example, with a function, creates a new function property when creating an instance, and therefore, a new key for Object.keys to pick up.

The second example, with a class, assigns the function property to the object's prototype instead. Because of this, a new key isn't actually created, and the sayName function will be found by walking up the prototype chain.

You can replicate the class behavior by doing this:

function AnimalFunc(name) {
  this.name = name
}

AnimalFunc.prototype.sayName = function () {
  console.log(this.name)
}

Here's some reading if you want to familiarize yourself with JS's prototype model. Can find more articles and such by searching up "javascript prototype", if you like.

like image 63
kingdaro Avatar answered Jan 31 '23 09:01

kingdaro


Because you have declared two properties named name and sayname

this.name;
this.sayname;

In the class AnimalClass you only declared as property the key name within the constructor body:

this.name = ....

Object.keys() returns an array whose elements are strings corresponding to the enumerable properties found directly upon object. The ordering of the properties is the same as that given by looping over the properties of the object manually.

So, basically will return the properties directly declared using the context this.

Example with class

  • Declaration of the function within the constructor's body

class AnimalClass {
  constructor(name) {
    this.name = name;
    // This is just to illustrate!
    this.sayName = function() {
      console.log(this.name);
    }
  }
}

console.log(Object.keys(new AnimalClass('Dog')))
like image 25
Ele Avatar answered Jan 31 '23 08:01

Ele