函数会假装是原生的吗?

时间:2017-01-31 15:58:31

标签: javascript

在JavaScript中,可以在强制转换为字符串时识别本机函数,例如:

console.log(document.getElementById);
// prints "function getElementById() { [native code] }"

但是,任何函数都可以重载toString()并假装是原生的:

function sum(a, b) {
  return a + b;
}

console.log(sum);
// prints "function sum(a, b) { return a + b; }"

sum.toString = function() { return 'function sum() { [native code] }'; };
console.log(sum);
// now prints "function sum() { [native code] }"

我正在查看Zone.js的源代码并找到了this bit,它正是这样做的(并且设计为according to one of the tests):

class ZoneAwarePromise<R> implements Promise<R> {
  static toString() {
    return 'function ZoneAwarePromise() { [native code] }';
  }

  ...

现在,我并没有要求猜测为什么Zone.js团队特别选择这样做(我无法找到任何官方博客文章/解释),而是:

  • 一般来说,你什么时候想要这样做?这样做有什么好处吗?

  • 是否有任何副作用,即JavaScript标准或任何JavaScript引擎是否以不同方式对待这些功能?

1 个答案:

答案 0 :(得分:3)

您正在检查的代码特定于Chromium引擎和MS Edge。

function eval() { [native code] }

在Firefox和Safari中,相同功能的字符串表示看起来很像:

function eval() {
    [native code]
}

在Internet Explorer中,字符串表示形式类似,只是在字符串的开头和结尾还有换行符。

因此,如果该代码假冒本机函数,至少它做得不好(或者它的节点特定?)。

除了在浏览器之间移植JSFuck之外,我不知道有任何实际用途。

确定某个函数是否为native的更安全的方法是获取Function.prototype.toString.call(fn)的结果(其中fn是正在测试的函数)并在预期位置搜索字符串[native code] 。这是所有浏览器中的不变量,但据我所知,它还没有完成规范。