Javascript: What's the difference between .call() and super()?

淺唱寂寞╮ 提交于 2019-11-29 05:08:11
  • super() calls the constructor of the class you extened

    class Foo extends Bar {
      constructor() {
        super();  // calls Bar's constructor
      }
     }
    
  • call is a generic function you can use with any function

    function a() { console.log(this); };
    function b() { console.log(this); };
    function c() { console.log(this}; };
    
    a.call("hello");
    b.call(123);
    c.call({});
    
  • super knows which class you inherited from and automatically passes the correct this.

    class Foo extends Bar {
      constructor() {
        super();  // calls Bar's constructor
      }
    }
    
  • call requires you to be explicit.

    class Foo extends Bar {
      constructor() {
        Bar.call(this);  // You had explicitly specify 'Bar' 
                         // and explicitly pass 'this'
      }
    }
    
  • super lets you call functions on the parent implicitly

    class Bar {
      log() { 
        console.log("bar-log");
      }
    }
    
    class Foo extends Bar {
      log() {
        super.log();
      }
    }
    
  • call requires you to be explicit

    class Bar {
      log() { 
        console.log("bar-log");
      }
    }
    
    class Foo extends Bar {
      log() {
        Bar.prototype.log.call(this);  // Explicitly reference bar's log function
                                       // and explicitly specify 'this'
      }
    }
    

I think you could argue super offers a subset of the functionality of call. Some might call it syntactic sugar meaning you can use call everywhere you can use super, super is just easier because it implicitly calls stuff from the class you extended/inherited from (technically the next thing up the prototype chain?) and because it implicitly passes this for you.

I imagine you relate call and super because of code like the following:

function Foo() {
   Bar.call(this)
}

class Foo extends Bar {
   constructor() {
      super()
   }
 }

In the case above, both examples do the same thing (call the constructor of Bar in the context of a new instance of Foo), but from there super and call differ greatly.

First off super is a key word, call is a method of Function's prototype.

The super keyword can be used to call the parent classes constructor and methods. So, in addition to the examples above super can do this:

class Bar {
  constructor() {
    //...
  }

  bang() {
    console.log('bang')
  }
}

class Foo extends Bar {
  constructor() {
    super()
    //...
  }

  bang() {
    // call parents method in context of `this`
    super.bang()

    //...
  }
}

call, on the other hand, is a method of the Function class that allows a function to be invoked with an explicit value for the this variable. Consider the following function.

function baz() { console.log(this.bar) }
baz() // -> "undefined"
baz.call({ bar: 'foo' }) // -> "foo"

The above example is actually a little more nuanced. Unless in strict mode, this will be the global object (global, window). In strict mode, this is undefined, and our baz function will throw an error. With call we can explicitly set this, a very powerful feature.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!