Search code examples
javascriptinheritanceprototypecallapply

using Call to inherit objects from a function


I was doing some testing and I got no clue why if using call I inherit from another object like, const objC = funcB.call(objA,'Erades') I got an object, but if I inherit from a function I got a function with wired (to me) behavior.

I don't understand why to get method B I have to do funcC.getLastName()

If anybody can help me to understand this...

TIA

// testing Call to inherit objects / functions
    // -------------------------------------------
    
    // we declare our first function
    const funcA = function(firstName) {
      this.firstName = firstName;
      this.getFirstName = function() {
          return 'My name is ' + this.firstName;
        };
      return this;
    };
    // Create an object out of that function
    const objA = new funcA('Rodrigo');
    
    // declare second function
    const funcB = function (lastName) {
      this.lastName = lastName;
      this.getLastName = function() {
        return 'My last name is ' + this.lastName;
      };
      return this;
    };
    
    // Create an Object from funcB and ObjectA
    const objC = funcB.call(objA,'Erades');
    // We get an object
    console.log("TYPE OF: ", typeof objC)
    console.log('raw:', objC);
    console.log('method A: ', objC.getFirstName());
    console.log('prop A: ', objC.firstName);
    console.log('method B: ', objC.getLastName());
    console.log('prop B: ', objC.lastName);
    console.log('------------');
    
    // if we don't want to create an object out of a function and an object,
    // we could also inherit two functions, but the result really surprise me 
    const funcC = funcB.call(funcA,'Alonso');
    // We get a function !!!!!
    console.log("TYPE OF: ", typeof funcC);
    console.log('raw:', funcC);
    // To get result we need to do this:
    console.log('method ==>: ', funcC('Rui'));
    console.log('method A: ', funcC('Rui').getFirstName());
    console.log('prop A: ', funcC('Maria').firstName);
    console.log('method B: ', funcC.getLastName()); // looks like static method ???
    console.log('prop B: ', funcC.lastName);
    console.log('------------');


Solution

  • You're not inheriting when you use call this way. You are passing an instance in and getting the same instance out with some modifications:

    const funcA = function(firstName) {
      this.firstName = firstName;
      this.getFirstName = function() {
          return 'My name is ' + this.firstName;
        };
      return this;
    };
    const objA = new funcA('Rodrigo');
    
    const funcB = function (lastName) {
      this.lastName = lastName;
      this.getLastName = function() {
        return 'My last name is ' + this.lastName;
      };
      return this;
    };
    
    const objC = funcB.call(objA,'Erades');
    // ObjC IS ObjaA
    console.log(objC === objA)

    When you use call the object passed in becomes the this of the function. You then add some properties and return this which is the same object you just passed in.

    Passing a function to call() is no different. When you write:

    funcB.call(funcA,'Alonso');
    

    you are calling the function funcB with Alonso as an argument. Inside that function this will refer to funcA. So you will set a lastName property on funcA and getLastName property pointing to a function, then return funcA which is then assigned to the variable funcC. funcC and funcA point to exactly the same function.

    const funcA = function(firstName) {
      this.firstName = firstName;
      this.getFirstName = function() {
          return 'My name is ' + this.firstName;
        };
      return this;
    };
    
    const funcB = function (lastName) {
      this.lastName = lastName;
      this.getLastName = function() {
        return 'My last name is ' + this.lastName;
      };
      return this;
    };
    
    
    const funcC = funcB.call(funcA,'Alonso');
    // the same reference
    console.log(funcC === funcA)
    // but when you called funcB with it, it added some properties:
    console.log("funC lastname:", funcC.lastName)
    // they are the same object so this also works: 
    console.log("also funcA lastname:", funcC.lastName)