Search code examples
javascriptcall

a is a function, then what `a.call.call` really do?


enter image description here

These codes are run on chrome devtool.

It seems like b.call(same as a.call.call) is calling the first argument, which is a function, then pass the second argument as this. If the first argument is not a function, then throw not a function error.

Can someone explain how <Function>.call.call work?


Solution

  • Let me show you an example.

    function a() { console.log(1) }
    
    function b() { console.log(2) }
    
    a.call(b)    // 1
    
    a.call.call(b)    // 2
    
    a.call.call.call(b)    // 2
    

    Why?

    We know a.call(b) means invoke a() with this value b.

    So that a.call.call(b) means invoke Function.prototype.call() with this value b, same as Function.prototype.call.call(b).

    But Function.prototype.call.call() is not an ordinary function Object. It can be invoked but it has no property. There's some unique rules to invoke it.

    Function.prototype.call.call(a)    // 1
    
    Function.prototype.call.call(b)    // 2
    

    In fact, Function.prototype.call.call(b) is an Exotic Object, furthermore, a Bound Function Exotic Object.

    • [Specification] A bound function is an exotic object that wraps another function object.

    • [Specification] Calling a bound function generally results in a call of its wrapped function.

    So that Function.prototype.call.call(a) simply means a().

    a.call.call(x) means invoke x, that is, x().

    • [Specification] In Function.prototype.call(thisArg), if thisArg is undefined or null, it will be replaced by global object.

    a.call.call() means a.call.call(undefined) means a.call.call(window) means invoke window.

    Try to invoke window you'll get Uncaught TypeError: window is not a function, so try to invoke a.call.call() you'll get Uncaught TypeError: a.call.call is not a function.

    Hope it helps.