如何在 class 静态方法中创建对象

How to create an object inside class static method

我开始在 classes 中学习更多关于静态方法的知识,并且想知道以下是否可行:

我的问题: 1. 这是一种糟糕的做法吗?如果不, 2.如何在静态方法中创建新实例?

我的第一个想法是,你可以只使用静态方法 return 一个对象,然后执行你想要的任何逻辑来随机化该对象的值,但我不确定是否有更好的方法. (我认为该对象将在使用 new Monster(...) 创建的实例的原型链之外?)

这是我第一次尝试时想到的,但这必然会创建 Monster,模仿 Monster class:

class Monster {
    constructor(hp) {
        this.hp = hp;
    }

    static create() {
        const obj = Object.create(Monster.prototype);
        obj.hp = Math.floor(Math.random() * 100);
        return obj;
    }

    attack(obj) {
        const randDamage = Math.floor(Math.random() * 10);
        console.log(`Monster deals ${randDamage} damage!`);
        obj.hp -= randDamage;
    }
}


const monster = Monster.create();
const me = {hp: 100};
monster.attack(me);
console.log(me);  // { hp: 91 }

有没有一种方法可以实现使用 Monster class 的 create()?或者这是正确的方法吗?

returns一个对象实例的函数通常被称为"factory function"。这是某些类型对象的常见设计模式。

对于你正在做的事情,你有几个选择:

  1. 您可以创建一个工厂函数,使 returns 以某种方式或随机方式预先设置的对象。

  2. 您可以创建一个构造函数变体(一组可以传递给构造函数的参数),这将导致它创建您想要的对象的类型和配置。

其中任何一个都可以同样有效。

Is this a terrible approach to doing this?

没有。工厂函数是一种非常合理的做事方式。通常,我会首先考虑让构造函数为您完成工作而不是使用工厂函数,但有时有充分的理由收集以某种方式将对象构建到工厂函数而不是构造函数中的特定序列。

How do you create a new instance inside the static method?

您使用 new 就像在其他任何地方一样。

Is there a way to implement create() that uses the Monster class?

是的。您只需在静态方法中使用 new 来创建对象。

// since your constructor already accepts an hp parameter as an argument
// you can just create a random hp value and pass it to the constructor
static create() {
    let hp = Math.floor(Math.random() * 100);
    return new Monster(hp);
}

但是,您也可以只修改您的构造函数,这样如果没有传递任何参数,那么构造函数本身会为其创建一个随机值,而根本不使用静态工厂函数:

class Monster {
    constructor(hp) {
        if (hp === undefined) {
            this.hp = Math.floor(Math.random() * 100);
        } else {
            this.hp = hp;
        }
    }

    // rest of class definition here

}

然后,只需使用构造函数创建您的对象:

// create monster object with random hp value
const monster = new Monster();

或者,如果你的参数足够简单,你可以使用 ES6 默认值:

class Monster {
    // supply default value for hp parameter if not present
    constructor(hp = Math.floor(Math.random() * 100)) {
        this.hp = hp;
    }
}

Allow someone to create a monster instance by passing all the properties they want the monster to have

这通常是通过将对象传递给构造函数以及对象上存在的任何属性来完成的,这些属性用于初始化对象的功能。如果传递给构造函数的对象不存在 属性,则构造函数将使用默认值。

class Monster {
    constructor(options) {
        if (options.hp === undefined) {
            this.hp = Math.floor(Math.random() * 100);
        } else {
            this.hp = options.hp;
        }
        // similar logic can be used for other properties on the options object

    }

    // rest of class definition here

}

此示例显示了检查对象上每个特定 属性 的代码,但这也可以通过将传入对象的所有属性复制到新创建的对象或通过创建白名单 属性 命名并复制白名单和对象中存在的任何内容。

或者,可以将传入的对象与属性的一组默认值合并,然后合并到新对象中。有很多方法可以做到这一点,具体取决于您拥有哪些特定属性以及您希望如何处理它们(如果它们存在或不存在)。