javascript - 在 Typescript 中扩展 {}(对象)

标签 javascript typescript extends

所以我试图扩展对象类。之所以是因为我想写一个函数叫isEqual

isEqual(object: any): boolean {
    return JSON.stringify(this) === JSON.stringify(object);
}

我尝试扩展 Object,但没有泛型类型。

我知道我可以使用一个带有两个参数并检查它的函数。但我想学习如何在 Typescript 中做到这一点。

我在 StackOverflow 上读到运算符重载是不可能的(因为最初我想使用 == 运算符来调用上面的函数)。

有人可以帮助我吗?

最佳答案

您希望向 the global Object type 的所有实例添加 isEqual() 方法。在 JavaScript 中,这可以通过将方法添加到 Object.prototype 来完成,并且对象的所有实例都将 inherit the method automatically .

在我说如何做之前,几乎普遍认为修改这样的原生原型(prototype)是一个坏主意。请参阅Why is extending native objects a bad practice?有关于此的官方 SO 答案。但简单地说:将 Object.prototype 视为 common property这需要每个人分享。如果您开始对其进行更改,而其他代码不需要这些更改,则该代码可能无法正常运行。相反,某些其他代码可能会进行更改,从而导致您的更改无法正常运行。

Object.prototype添加方法的简单方法,例如Object.prototype.isEqual = ...Object.defineProperty(Object.prototype , 'isEqual', {value(...){...}}) 最终会将 isEqual 作为 enumerable property所有对象,这意味着 for...in loop会突然显示 "isEqual" 作为到处可能的对象的键。

这里的官方建议是不要这样做


如果您仍然想这样做(例如,也许您正在使用其他人不需要与之交互的代码来执行此操作,因此唯一可能受到此伤害的人就是您),那么这里是如何操作的。 TypeScript 支持declaration merging允许添加现有接口(interface):

interface Object {
  isEqual(object: object): boolean;
}

如果您这样写,编译器现在会期望所有 Object 都具有 isEqual() 方法。 (如果您的代码位于模块中,则需要将其包装在 declare global { } block 中,称为 global augmentation )。

当然你还得实现它:

Object.defineProperty(Object.prototype, 'isEqual', {
  value(object: object) {
    return JSON.stringify(this) === JSON.stringify(object);
  },
  configurable: true,
  enumerable: false // <-- we don't want to mess with for...in loops
});

这里我使用了the Object.defineProperty() method这样我们就可以显式地阻止方法名称可枚举。

现在您可以验证它是否按预期工作:

interface Foo { a: number, b: string };
const o1: Foo = { a: 1, b: "two" };
const o2: Foo = { b: "two", a: 1 };
console.log(o1.isEqual(o2)); // false

o1.isEqual(o2) 编译时没有错误,当您运行它时,它会使用您的 isEqual() 方法,并返回 false 正如预期的那样。 (您确实期望错误,对吗?如果没有,请参阅sort object properties and JSON.stringify。)

Playground link to code

关于javascript - 在 Typescript 中扩展 {}(对象),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74000085/

相关文章:

javascript - LINQ Group by & Select FirstOrDefault() 的 Lodash 或 JavaScript 等价物

javascript - 为什么 Angular 加载我的根模板两次

Java multiple extends Zk Component 变得非常冗长

javascript - Angular 7 标题未设置

java - 接口(interface)和类中的方法签名相同

java - Android Java - 为什么不扩展 Activity -> 新 Activity

javascript - 验证为电话号码

javascript - 我可以在 object.defineProperty() 上传递属性数组吗?

JavaScript循环混合div

javascript - 通过 alpha channel 的图像贴图