1

The context:

I am reading the book You Don't Know JS: Up & Going, Chapter 2: Into JavaScript. In the Polyfilling section, the author gives the following example:

if (!Number.isNaN) {
    Number.isNaN = function isNaN(x) {
        return x !== x;
    };
}

So, what is being done here is creating a polyfill so that the ES6 method Number.isNaN can run in older browsers (ie, pre-ES6 versions). As I expected, he makes use of the older isNaN method. The former method is actually meant to deprecate the latter by design.

The question:

Why is isNaN being used as the identifier of the named function expression? I would have expected it to be used in the body somehow. Why? Because all of the identifiers usually seen in examples around the web, when comparing function expressions vs function declarations take the following form:

Function declaration:

function foo() {
    // ..
}

Function expression:

var foo = function bar() {
    // ..
};

So in this example bar is being defined within the brackets after the 'bar()' string. So why use 'isNaN' above when isNaN is an already defined function within JavaScript? Are we actually overwriting it for the purpose of the polyfill? What am I missing/misunderstanding here?

  • naming the function that way doesn't really do anything to the old `isNaN`, it's mostly done for stack traces or to be able to reference the function from within itself. In this example the function could just as well be anonymous. – adeneo May 15 '17 at 15:34
  • `Function declaration` - will be created BEFORE code execution, `Function expression` - will be created, when line of code with initialization will be riched by interpreter. in your case this prevents overwriting a function `isNaN` before check – Andrew Evt May 15 '17 at 15:34
  • @AndrewEvt I understand both definitions and how the Engine treats one and the other. However I don't understand your second sentence: "in your case this prevents overwriting a function isNaN before check". Can you explain what you mean? How is overwriting prevented, and as opposed to which case? – user3723667 May 29 '17 at 15:53

1 Answers1

1

When you have a named function in an expression, that value is not hoisted but is saved in expression scope. So original value is not changed.

Sample

function bar(){
  console.log("In Bar")
}

var foo = function bar(){
  console.log("In Foo")
}

bar();
foo();

Why should you use it?

In case of exception, that will help you in debug. An anonymous function will not show any name in stack trace and if you have say 4-5 anonymous functions in 1 function, it becomes difficult as to which one failed. Having a named functions makes it little simple.

var bar = function Test() {
  (function() {
    (function() {
      (function() {
        throw new Error("I have no Name2")
      })()
    })()
  })()
}

var foo = function Test() {
  (function inFoo1() {
    (function inFoo2() {
      (function inFoo3() {
        throw new Error("I have no Name2")
      })()
    })()
  })();
}


function init() {
  try {
    foo();
  } catch (ex) {
    console.log(ex.stack)
  }
  try {
    bar();
  } catch (ex) {
    console.log(ex.stack)
  }
}

function start() {
  init();
}

start();

You can also refer to Why using named function expressions? for more information.

Community
  • 1
  • 1
Rajesh
  • 24,354
  • 5
  • 48
  • 79