我有一个带有构造函数的抽象类型脚本类.此构造函数接受对象,然后try 使用对象中的数据设置类的属性.

export default class AbstractModel {
    constructor(properties: object) {
        Object.assign(this, properties);
    }
}

然后有几个类继承了这AbstractModel个类. 例如:

import AbstractModel from "./abstract-model";

export default class Derived extends AbstractModel {
    firstname!: string;
    lastname!: string;
    age: number = 1;
}

我的假设是,当我创建一个新的Derived并在构造函数中传递{age: 10}时,新创建的Derivedage设置为10.然而,年龄似乎总是1的初始值.其他没有初始值的属性正在按预期进行设置.

const derived = new Derived({firstname : "John", lastname: "Doe", age: 10});

输出:

Derived {
  firstname: 'John',
  lastname: 'Doe',
  age: 1,
}

将其记录在AbstractModel的构造函数中会得到以下输出

export default class AbstractModel {
    constructor(properties: object) {
        Object.assign(this, properties);
        console.log(this);
    }
}

输出:

Derived {
  firstname: 'John',
  lastname: 'Doe',
  age: 10,
}

将其记录在Derived的构造函数中会得到以下输出

export default class Derived extends AbstractModel {
    firstname!: string;
    lastname!: string;
    age: number = 1;

    constructor(properties: object) {
        super(properties);
        console.log(this);
    }
}

输出:

Derived {
  firstname: 'John',
  lastname: 'Doe',
  age: 1,
}

有谁能告诉我为什么它会这样?

推荐答案

您为age提供的初始值由您的子类构造函数指定/定义.赋值/定义是在子类构造函数(如果提供显式构造函数,则是显式构造函数,如果没有提供,则是默认生成的构造函数)中调用super之后完成的.因此,age将是您的子类中的1,因为超类构造函数完成的赋值将被覆盖.下面是一个更简单的示例(只需使用JavaScript,这样我们就可以在Stack代码片断中运行它):

class Base {
    construct或() {
        this.age = 42;
    }
}
class Derived extends Base {
    age = 1;
}

console.log(new Derived().age);

Derived生成的构造函数为:

construct或(...args) {
    super(...args);
}

..而定义/分配<$设置age1发生在super(...args)部分之后.

我认为在您所展示的代码中修复它的最简单的方法是删除缺省值,并提供一个Derived的构造函数:

age: number;
construct或(obj: object) {
    super(obj);
    this.age = (obj as any).age ?? 1;
}

age!: number;
// ^−−− Note the "definitely assigned" assertion
construct或(obj: object) {
    super({age: 1, ...obj});
}

或 similar (playground link).

That said, the AbstractModel construct或 code isn't typesafe, it'll copy over any and all own properties of the object you provide it. You may want to refact或 that.


¹ Whether Derived does an assignment (effectively, this.age = 1) 或 a redefinition (Object.defineProperty(this, "age", {value: 1, /*...*/})) depends on the useDefineF或ClassFields configuration option. It does assignment when the option isn't enabled, and redefinition when it is. Redefinition is the way JavaScript's class fields are standardized, so the configuration option was added to TypeScript to supp或t that newly-standard behavi或 when class fields were introduced to JavaScript.

Javascript相关问答推荐

Vue:ref不会创建react 性属性

如何避免移动设备中出现虚假调整大小事件?

如何最好地从TypScript中的enum获取值

通过在页面上滚动来移动滚动条

从WooCommerce Checkout Country字段重新排序国家,保持国家同步

如何粗体匹配的字母时输入搜索框使用javascript?

实现JS代码更改CSS元素

如何在Angular17 APP中全局设置AXIOS

在HTML语言中调用外部JavaScript文件中的函数

在数组中查找重叠对象并仅返回那些重叠对象

将数组扩展到对象中

当我try 将值更改为True时,按钮不会锁定

expo 联系人:如果联系人的状态被拒绝,则请求访问联系人的权限

如何访问此数组中的值?

在Vercel中部署Next.js项目时获取`ReferenceError:未定义文档`

如何在移动设备中使用JAVASSCRIPT移除点击时的焦点/悬停状态

Django模板中未加载JavaScript函数

在点击链接后重定向至url之前暂停

使用Java脚本筛选数组中最接近值最小的所有项

为什么我的Reaction组件不能使用createBrowserRouter呈现?