Javascript类与“Javascript类”;列表“;Nodejs中函数的定义

Javascript类与“Javascript类”;列表“;Nodejs中函数的定义,javascript,node.js,function,class,Javascript,Node.js,Function,Class,我是一个编程新手,我现在想知道在NodeJs中类相对于简单的相关函数“列表”有什么好处 作为一个非常简单的例子,如果我使用Class,我想我会创建一个这样的用户: class User { constructor(email) { this.email = email; } validateEmail() { // whatever function that checks if this.email is valid i

我是一个编程新手,我现在想知道在NodeJs中类相对于简单的相关函数“列表”有什么好处

作为一个非常简单的例子,如果我使用Class,我想我会创建一个这样的用户:

class User {
    constructor(email) {
        this.email = email;
    }

    validateEmail() {
        // whatever function that checks if this.email is valid
        if (this.email === 'notValid') {
            throw new Error();
        }
        return this;
    }

    create() {
        this.validateEmail();
        // whatever function that inserts user in the database
        return user;
    }
}

const newUser = new User('test@test.com');
const user = newUser.create();
我会用我称之为相关函数的“列表”来做这样的事情:

const validateEmail = email => {
    // whatever function that checks if valid email
    if (email === 'notValid') {
        throw new Error();
    }
    return true;
};

const createUser = email => {
    if (validateEmail(email)) {
        // whatever function that inserts the user in the database
        return user;
    }
};

const user = createUser('test@test.com');
第二种方式在我看来,它可以以更少的代码结束。甚至不必让班级停课

假设我有一个节点API,有多个“用户”路由和控制器。我想每次调用用户routes/controller时,我都必须实例化用户类,对吗?作为一个初学者,这听起来并不“优化”给我。。。但我肯定错过了一些东西

感谢您的帮助

类将数据(此实例上的属性)与功能(每个实例的内部原型上的函数)联系起来

如果您没有与实例关联的数据,那么创建类就没有多大意义。在这里,您确实有数据(电子邮件字符串)和相关函数(
validateEmail
),因此类是一个可能的选项,尽管当涉及更多属性和函数时会更好。(如果只有一个属性,并且该属性只存在于其中,因此可以使用该函数调用它,那么类确实看起来不必要地冗长。)

此类类的一个好处是,一旦拥有实例,就可以将该实例传递给任何其他模块(或作用域),并且该模块可以调用与该实例相关的函数,而无需导入等效的独立函数。例如,假设您的用户类的使用者位于不同的模块中,并且使用者希望能够创建用户并对其进行验证。然后,导出大部分用户代码的模块必须

(1) 导出许多独立函数(这可能会变得有点乏味和难以管理),或者

(2) 只导出一个类

能够只导出一个类,并让该类或其实例的任何用户使用与类相关的方法非常方便——这样,您就不必在每次需要使用与用户相关的函数时传递多个值

想象一下,如果模块A需要能够创建用户,模块B需要能够验证用户,模块C需要能够检查用户是否已经验证。如果主用户文件为这些东西中的每一个创建并导出独立函数,并且每个消费模块都导入了它们需要调用的东西,那么事情就有点糟糕了。但是,如果主用户文件创建并导出了一个类,那么它将是微不足道的:用户(模块a)的创建者将导入该类,实例化一个对象
const User=new User('a@a.com,并将其传递给模块B,然后模块B可以调用
user.validateEmail()
(无需导入)。最后,用户实例被传递到模块C,模块C调用
user.checkIfUserIsValidated()
(同样,不需要导入)

使用类方法,在同一个对象(类实例)上有一个同时包含实例数据和相关函数的对象,可以使代码更干净


当然,如果您不想使用类,您不必使用它,但这是一个可能的好处。

通过您给出的示例,您确实有一点:

  • 验证电子邮件的函数实际上并不需要实例化的对象来执行操作,事实上,您希望在创建API的对象实例之前运行该函数

  • 如果函数返回一个不同的对象(
    user
    不是
    user
    的实例),而不改变
    这个
    对象,这也不是创建单独类的最佳理由。如果与您已经可以访问的API对象类(返回
    user
    )相比,这(电子邮件验证)是您需要做的“额外”工作,那么第二种方法就可以了

但是,如果您想要扩展该API,那么您还可以使用其他一些功能,比如:

  • 准备一封个性化的电子邮件,您需要他们的姓名、地址、电子邮件、性别等
  • 根据几个属性(年龄、上次登录日期、访问级别等)返回一些计算出的分数
…那么使用第一种模式可能会更好——尽管这仍然是一个意见问题

我建议仍然创建您自己的类,但让它立即创建API的对象,并使返回的对象值成为您自己实例的属性。然后,这个新对象是API接口的一个组成部分,带有您自己的扩展

也许是这样:

function validateEmail(email) {
    // whatever function that checks if an email is valid
    if (email === 'notValid') {
        throw new Error();
    }
}

class User  {
    constructor(email) {
        this.rank = 10; // Let's say you need this property that is not offered by the API
        validateEmail(email);
        // whatever function that inserts user in the database
        this.apiUser = api.createUser(email);
    }

    promote() { // Some function using the new properties
        if (this.rank > 1) this.rank--;
    }

    prepareEmail() { // Other function using a mix
        return {
            sentBy: "admin@mysite.com",
            to: this.apiUser.get("email"),
            body: `Dear ${this.apiUser.get("name")}, your current rank is ${this.rank}`
        };
    }
}

const user = new User('test@test.com');

因此,这里您可以看到主代码创建了一个对象实例。API的对象实例封装在其中。您可以允许调用方使用
user.apiUser.someapiemember
语法直接使用API,也可以在自己的类中创建自己的包装函数,以
user.myApiWrapperMember
的身份访问。我建议您阅读一下面向对象设计和体系结构的好处。这是一个巨大的话题,你可以阅读整本书。简单的示例可能与面向对象设计相似,也可能与面向对象设计相似,但更多涉及的示例与面向对象设计相比要简单几个数量级。查找单词“封装”、“继承”、“多态性”、“模块化”、“数据抽象”、“名称空间”和“可重用性”。搜索“面向对象设计的好处”并阅读。当然,并不是每一段代码都能最好地应用到对象设计中。有些问题只是程序性的。当有一组操作都对一组共享数据进行操作时,面向对象的设计最适合。在GUI中查看具有大量m的窗口对象