1

上下文

我正在阅读《你不知道 JS:Up & Going》第 2 章:进入 JavaScript的书。在Polyfilling部分,作者给出了如下示例:

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

所以,这里要做的是创建一个 polyfill,以便 ES6 方法Number.isNaN可以在旧浏览器(即 ES6 之前的版本)中运行。正如我所料,他使用了旧的isNaN方法。前一种方法实际上旨在通过设计弃用后者。

问题

为什么 isNaN 被用作命名函数表达式的标识符?我原以为它会以某种方式在体内使用。为什么?因为在网络上的示例中通常会看到所有标识符,所以在比较函数表达式和函数声明时,采用以下形式:

函数声明:

function foo() {
    // ..
}

函数表达式:

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

所以在这个例子中bar被定义在 'bar()' 字符串之后的括号内。那么,当isNaN是 JavaScript 中已经定义的函数时,为什么还要使用上面的 'isNaN'呢?我们实际上是为了 polyfill 的目的而覆盖它吗?我在这里错过/误解了什么?

4

1 回答 1

1

当表达式中有命名函数时,该值不会被提升,而是保存在表达式范围内。所以原始值不会改变。

样本

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

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

bar();
foo();

为什么要使用它?

如果出现异常,这将帮助您进行调试。匿名函数不会在堆栈跟踪中显示任何名称,如果您在 1 个函数中有 4-5 个匿名函数,那么很难确定哪个函数失败了。有一个命名函数使它变得有点简单。

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();

您还可以参考为什么要使用命名函数表达式?了解更多信息。

于 2017-05-15T15:48:40.967 回答