2

I'm well aware that javascript is not a class based language.

With that being said here is an example of (one of the ways) we do inheritance in JavaScript:

function Person(name, age) {
        this.name = name;
        this.age = age;
    }

    Person.prototype.introduceSelf = function() {
        console.log("My name is " + this.name + " and I'm " + this.age);
    }

    function Employee(name, age, employeeID) {
        Person.call(this, name, age);
        this.employeeID = employeeID;
    }

    Employee.prototype = Object.create(Person.prototype);

    Employee.prototype.sayEmployeeID = function() {
        console.log('My Employee ID is: ' + this.employeeID);
    }

    var joe = new Employee('Joe', 22, 42);
    joe.introduceSelf() // returns: My name is joe and I'm 22
    joe.sayEmployeeID() // returns: My Employee ID is: 42

My question is: how does simply calling Person.call(this, name, age) within the Employee constructor, result in the object having the name and age property when calling new Employee(...)

I understand that it's calling the Person function with the this being the context within Employee but It's not clear how the properties get onto the resulting object. What exactly is happening "under the hood?"

  • I'd suggest investing a lot of time studying JavaScript closures. https://stackoverflow.com/questions/111102/how-do-javascript-closures-work – Kris Oct 18 '17 at 03:06
  • 2
    @Kris that has nothing to do with closure, it is just the nature of javascript which operates on "dynamic" `this` pointer which drives those who dont understand it crazy. That's why you can "borrow" functions in javascript, the popular pattern often seen is `Array.prototype.slice.call(nodeList)` to convert a `NodeList` to an array before the addition of `Array.from` – Trash Can Oct 18 '17 at 03:08
  • This is because when the `new` instanceof `Employee` is called `Person` is called width it's `this` bound to the instanceof `Employee`. – StackSlave Oct 18 '17 at 03:12
  • @PHPglue I get why it occurs, but it's not clear how those properties get added to the instance. If you were to copy and paste the code into the JS console, simply running `Person.call(this, 'window', 1)` would not result in `name` or `age` properties added to the window. It's only when called within the context of a constructor function that the resulting object has the properties from another constructor function/object – Rosel Padilla Oct 18 '17 at 03:21
  • It does work. `Person.call(this, 'window', 1); console.log(name);` you get `window`. `this` is in the global context like that. – StackSlave Oct 18 '17 at 03:35
  • @PHPglue You're right it does. However I'm still curious about what happens between the `Person.call(...)` call, and the properties being "placed" on the window/instance/etc. object. – Rosel Padilla Oct 18 '17 at 03:39
  • Check out this answer: https://stackoverflow.com/a/4778408/878906 – Doug Coburn Oct 18 '17 at 06:35

2 Answers2

3

I understand that it's calling the Person function with the this being the context within Employee

Do you also understand what the "context within Employee" is? It's the new instance, the resulting object, that the new operator created before running the constructor function's body (Employee in new Employee). See What is the 'new' keyword in JavaScript? for details.

It's not clear how the properties get onto the resulting object. What exactly is happening "under the hood?"

The properties get created by the assignments:

this.name = name;
this.age = age;
…
this.employeeID = employeeID;

Again, this refers to the resulting object. In the former two cases, because the call method was explicitly used on Person, in the latter case because new was used on Emloyee.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
2

Within the method of an Object the this context belongs to the Object's context. In the case of Person, it is an instanceof Function, which has it's this context bound to the global context (window in Client Side JavaScript). A new instance creates a new (independent with the exception of it's prototype inheritance) Object and the this context is bound to it. new instances also return this if a return value is not specified. This should also explain why the this context in an EventListener is attached to the Object to which it belongs... the Element.

To daisy chain your instance methods, it's a common practice to return this; within them.

StackSlave
  • 10,613
  • 2
  • 18
  • 35