Search code examples
javascripttypechecking

Redundant type checking for function?


In the Polyfill section of the Array.prototype.forEach js mdn, you can find the following check:

if (typeof callback !== 'function') {
    throw new TypeError(callback + ' is not a function');
}

In this specific case, why bother checking for function? During my tests, calling the function directly yields the exact same behavior

var callback;
callback();
// Uncaught TypeError: callback is not a function

var callback = "";
callback();
// Uncaught TypeError: callback is not a function

var callback = 2;
callback();
// Uncaught TypeError: callback is not a function

var callback = [];
callback();
// Uncaught TypeError: callback is not a function

var callback = {};
callback();
// Uncaught TypeError: callback is not a function

Actually it's a little bit worse with this type of string concatenation, because we might see "[object Object] is not a function":

function newCallback(val){
    if (typeof val !== 'function') {
        throw new TypeError(val+ ' is not a function');
    }
}
newCallback({});
//Uncaught TypeError: [object Object] is not a function

Solution

  • In this specific case, why bother checking for function?

    If the array is empty, there won’t be an attempt to call the function, but it should still fail.

    [].forEach('foo')

    There’s also a difference for non-empty arrays when element access has side-effects:

    let foo = {
        get [0]() {
            alert(1);
        }
    };
    
    Array.prototype.forEach.call(foo, …);
    // alert shows up if the early type check is missing