【问题标题】:Extend native JavaScript Number object in TypeScript在 TypeScript 中扩展原生 JavaScript Number 对象
【发布时间】:2015-09-01 11:10:17
【问题描述】:

根据 TypeScript 文档,扩展现有接口就像使用新属性重新声明它一样简单,然后为这些属性提供实现。我已经多次使用这种技术向原生 JavaScript 对象添加静态方法扩展。但是,这不适用于成员函数。

例如(TypeScript Playground link):

interface Number {
  toPowerOf10: () => string;
}

Number.prototype.toPowerOf10 = (): string => { 
  return this.toExponential();
}

var n: Number = 10000;
n.toPowerOf10();

上面的代码编译正常,但是在运行时,它会抛出以下异常:

Uncaught TypeError: _this.toExponential is not a function

罪魁祸首似乎是 TypeScript 如何为这种场景生成 JavaScript 代码:

var _this = this;
Number.prototype.toPowerOf10 = function () {
    return _this.toExponential();
};
var n = 1000;
alert(n.toPowerOf10());

很明显_this 在这里没有引用Number 实例。我不确定我是否做错了什么,或者 TypeScript 不支持以这种方式扩展原生对象。

【问题讨论】:

  • 非常有趣的问题!使用 function () { 而不是 (): string => { 为我解决了这个问题,有人知道规范吗?这是期望的行为还是错误?
  • @olydis 使用箭头函数将捕获外部范围,因此这是预期的行为。但是,如果您使用 implements Number 实现了自己的 Number 类,那么使用箭头就可以了。将函数分配给原型是这里的方法
  • 顺便说一句,像这样向原型添加函数是不好的做法。它们将来可能会被覆盖。

标签: javascript typescript


【解决方案1】:

这是因为您使用箭头符号 (=>) 来声明新函数,而不是 function。虽然=> 似乎是同一事物的一个很好的速记,但它和function 并不完全等价。特别是,=> 将进行词法作用域,这意味着该函数的 this outside 将引用与该函数的 this inside 相同的东西,它通过在已编译的 JavaScript 中捕获本地 _this 来完成。在这里,this 是全局范围,因为您在那里声明了 Number 扩展。如果这是浏览器this会引用window对象,当然它没有toExponential方法。

要完成您想要的,只需使用以下内容:

declare global {
    interface Number {
          toPowerOf10: () => string;
    }
}

Number.prototype.toPowerOf10 = function() : string {
  return this.toExponential();
}

var n: Number = 10000;
document.write(n.toPowerOf10());

【讨论】:

  • 只是一个小提示:显式命名类型仍然是可能的 (function(): string {)
  • 另外,假设这是问题的实际表示,Number.prototype.toPowerOf10 = Number.prototype.toExponential; 将是等效的
  • @JulianR 谢谢。工作完美。我不知道=> 的含义略有不同。你每天学习新的东西。 @RGraham这只是为了节省问题空间的简化:)
  • 这似乎不再编译,除非您在接口定义周围添加declare global {
  • 全局范围的增强只能直接嵌套在外部模块或环境模块声明中。
猜你喜欢
  • 1970-01-01
  • 2013-07-20
  • 2017-11-10
  • 2012-12-09
  • 2012-05-12
  • 2019-02-09
  • 2016-05-06
  • 1970-01-01
  • 2016-08-22
相关资源
最近更新 更多