使用类创建角色的 JavaScript 功能

Posted

技术标签:

【中文标题】使用类创建角色的 JavaScript 功能【英文标题】:JavaScript functionality to create roles with classes 【发布时间】:2021-12-20 03:04:21 【问题描述】:

我的任务是实现在 JS 中创建角色的功能,每个角色都由其类型(访客、用户、管理员)定义。

    Guest 类型应具有:获取任务数组的方法(constructor); 获取任务 id(数组索引)并从任务数组中返回任务的方法(getTask) 不应定义 createTaskchangeType 类型 User 也应该有 constructor 就像在 Guest 中一样,也是一个方法 getTaskcreateTask -a将新任务添加到任务数组的方法 不应定义 changeTypeAdmin 类型应该有构造函数——一个获取客人和用户数组的方法;

getArray-返回客人和用户数组的方法

changeType - 一个获取数字(数组索引)的方法在提供的索引处修改数组项(将对象类型从访客更改为用户,否则,结果,任务应该从一种类型迁移到另一种类型),并返回修改后的项目数组

所以,我创建了所有的类和方法,但是在最后当我用 npm 测试它时,我得到的消息是:

来宾不应实现方法 createTask Guest 不应实现方法 changeType 用户不应实现方法 changeType 管理员应将角色类型从用户更改为访客

但是当我在浏览器的控制台中引入它们时,一切正常,但我观察到当我编写 guest.createTask 时,它显示它未定义并且不会引发错误,但我认为我应该得到错误。

这是我的代码:

class Task 
    constructor(name) 
        this.name = name;
    

class Guest 
    constructor(tasks) 
        this.tasks = tasks;
    
    getTask(index) 
        return this.tasks[index];
    


class User 
    constructor(tasks) 
        this.tasks = tasks;
    
    getTask(index) 
        return this.tasks[index];
    
    createTask(tasks) 
        return this.tasks.push(tasks);
    


class Admin 
    constructor(userGuestArray) 
        this.userGuestArray = userGuestArray;
    
    getArray() 
        return this.userGuestArray;
    

    changeType(index, replace, arr) 
        replace = this.userGuestArray;
        arr = this.userGuestArray[index];
        if (replace[index] = Guest) 
            replace[index] = new User(arr.tasks);

        if (replace[index] = User)
            replace[index] = new Guest(arr.tasks);

        

        return replace;
    

这里是测试Guest类的代码:

const guest = new Guest(
    [
      new Task('task name 1'),
      new Task('task name 2'),
      new Task('task name 3'),
    ]
  );
expect(guest.getTask(0).name).to.equal('task name 1');
expect(guest.getTask(2).name).to.equal('task name 3');
const guest = new Guest([]);
expect(guest.createTask).to.throw('method \'createTask\' is not defined');
expect(guest.changeType).to.throw('method \'changeType\' is not defined');

下面是管理员更改类型角色:

admin = new Admin([
              new Guest([]),
              new Guest([new Task('task name 1')]),
              new User([]),
              new User([new Task('task name 2')]),
        ]);
 it('should change type of role from Guest to User', () => 
        expect(admin.getArray()[0] instanceof Guest).to.equal(true);
        admin.changeType(0);
        expect(admin.getArray()[0] instanceof User).to.equal(true);
    );

    it('should change type of role from User to Guest', () => 
        expect(admin.getArray()[3] instanceof User).to.equal(true);
        admin.changeType(3);
        expect(admin.getArray()[3] instanceof Guest).to.equal(true);
        
    );

    it('should move tasks from Guest to User, when change role', () => 
        expect(admin.getArray()[1].getTask(0)).to.deep.equal( name: 'task name 1');
        admin.changeType(1);
        expect(admin.getArray()[1].getTask(0)).to.deep.equal( name: 'task name 1');
    );

请帮助解决错误,我已经把我的大脑烧坏了。我试图将方法设为私有,但我认为我做的不对而且不起作用。我不知道该怎么办了。 PS:我是 JS 新手,正在尝试学习这些任务。

这是理解作业的整个测试脚本:

const Task, Guest, User, Admin = require('../src');
const chai = require('chai');
const  expect  = chai;

describe('Guest', () => 
  it('should have method getTask', () => 
    const guest = new Guest(
        [
          new Task('task name 1'),
          new Task('task name 2'),
          new Task('task name 3'),
        ]
      );
      console.log(1,guest);
      expect(guest.getTask(0).name).to.equal('task name 1');
      console.log(2,guest.getTask(0).name);
      expect(guest.getTask(2).name).to.equal('task name 3');
      console.log(3,guest.getTask(2).name);
  );

  it('should not implement method createTask', () => 
    const guest = new Guest([]);
    console.log(4,guest);
    expect(guest.createTask).to.throw('method \'createTask\' is not defined');
    console.log(5,guest.createTask);
  );

  it('should not implement method changeType', () => 
    const guest = new Guest([]);
    console.log(6,guest);
    expect(guest.changeType).to.throw('method \'changeType\' is not defined');
    console.log(7,guest.changeType);
  );
);

describe('User', () => 
    let user;
    beforeEach(() => 
        user = new User(
            [
              new Task('task name 1'),
              new Task('task name 2'),
              new Task('task name 3'),
            ]
          );
    )
    console.log(8,user);
    it('should have method getTask', () => 
        expect(9,user.getTask(0).name).to.equal('task name 1');
        console.log(user.getTask(0).name)
        expect(10,user.getTask(2).name).to.equal('task name 3');
    );

    it('should have method createTask', () => 
        expect(user.getTask(0).name).to.equal('task name 1');
        console.log(11,user.getTask(0).name);
        expect(user.getTask(2).name).to.equal('task name 3');
        console.log(12,user.getTask(2).name);
        user.createTask(new Task('task name 4'))
        console.log(13,user.createTask(new Task('task name 4')));
        expect(user.getTask(3).name).to.equal('task name 4');
        console.log(14,user.getTask(3).name);
    );

    it('should not implement method changeType', () => 
        const user = new Guest([]);
        console.log(15,user);
        expect(user.changeType).to.throw('method \'changeType\' is not defined');
        console.log(16,user.changeType);
    );
);

describe('Admin', () => 
    let admin;
    beforeEach(() => 
        admin = new Admin([
              new Guest([]),
              new Guest([new Task('task name 1')]),
              new User([]),
              new User([new Task('task name 2')]),
        ]);
    )
    console.log(17,admin);
    it('should have method getArray', () => 
        expect(admin.getArray().length).to.equal(4);
    );
console.log(18,admin.getArray().length);
    it('should return instance of Guest as a first element by the method getArray', () => 
        expect(admin.getArray()[0]).to.deep.equal( tasks: []);
    );
console.log(19,admin.getArray()[0]);
    it('should return instance of User as a third element by the method getArray', () => 
        expect(admin.getArray()[3]).to.deep.equal( tasks: [ name: 'task name 2']);
    );
console.log(20,(admin.getArray()[3]));
    it('should return array of roles by the method getArray', () => 
        expect(admin.getArray()).to.deep.equal([ tasks: [],  tasks: [ name: 'task name 1'],  tasks: [],  tasks: [ name: 'task name 2']]);
    );
console.log(21,admin.getArray())
    it('should change type of role from Guest to User', () => 
        expect(admin.getArray()[0] instanceof Guest).to.equal(true);
        console.log(22,admin.getArray()[0] instanceof Guest);
        admin.changeType(0);
        console.log(23, admin.changeType(0));
        expect(admin.getArray()[0] instanceof User).to.equal(true);
        console.log(24,admin.getArray()[0] instanceof User);
    );

    it('should change type of role from User to Guest', () => 
        expect(admin.getArray()[3] instanceof User).to.equal(true);
        console.log(25,admin.getArray()[3] instanceof User);
        admin.changeType(3);
        console.log(26,admin.changeType(3));
        expect(admin.getArray()[3] instanceof Guest).to.equal(true);
        console.log(27,admin.getArray()[3] instanceof Guest)
    );

    it('should move tasks from Guest to User, when change role', () => 
        expect(admin.getArray()[1].getTask(0)).to.deep.equal( name: 'task name 1');
        console.log(28,admin.getArray()[1].getTask(0));
        admin.changeType(1);
        console.log(29,admin.changeType(1));
        expect(admin.getArray()[1].getTask(0)).to.deep.equal( name: 'task name 1');
        console.log(30,admin.getArray()[1].getTask(0));
    );

    
);

不要关注控制台日志,我尝试调试我的代码以查看错误在哪里。 错误日志:

        <?xml version="1.0" encoding="UTF-8"?>
<testsuites name="Mocha Tests" time="0.0090" tests="13" failures="5">
  <testsuite name="Root Suite" timestamp="2021-11-06T12:36:46" tests="0" time="0.0000" failures="0">
  </testsuite>
  <testsuite name="Guest" timestamp="2021-11-06T12:36:46" tests="3" file="C:\Users\artio\Desktop\6 Classes\8.2.classes\test\index.js" time="0.0040" failures="2">
    <testcase name="Guest should have method getTask" time="0.0010" classname="should have method getTask">
    </testcase>
    <testcase name="Guest should not implement method createTask" time="0.0010" classname="should not implement method createTask">
      <failure message="expected undefined to be a function" type="AssertionError"><![CDATA[AssertionError: expected undefined to be a function
    at Context.<anonymous> (test\index.js:21:38)
    at processImmediate (internal/timers.js:439:21)]]></failure>
    </testcase>
    <testcase name="Guest should not implement method changeType" time="0.0000" classname="should not implement method changeType">
      <failure message="expected undefined to be a function" type="AssertionError"><![CDATA[AssertionError: expected undefined to be a function
    at Context.<anonymous> (test\index.js:26:38)
    at processImmediate (internal/timers.js:439:21)]]></failure>
    </testcase>
  </testsuite>
  <testsuite name="User" timestamp="2021-11-06T12:36:46" tests="3" file="C:\Users\artio\Desktop\6 Classes\8.2.classes\test\index.js" time="0.0010" failures="2">
    <testcase name="User should have method getTask" time="0.0000" classname="should have method getTask">
      <failure message="task name 1: expected 9 to equal &apos;task name 1&apos;" type="AssertionError"><![CDATA[AssertionError: task name 1: expected 9 to equal 'task name 1'
    at Context.<anonymous> (test\index.js:42:43)
    at processImmediate (internal/timers.js:439:21)]]></failure>
    </testcase>
    <testcase name="User should have method createTask" time="0.0000" classname="should have method createTask">
    </testcase>
    <testcase name="User should not implement method changeType" time="0.0000" classname="should not implement method changeType">
      <failure message="expected undefined to be a function" type="AssertionError"><![CDATA[AssertionError: expected undefined to be a function
    at Context.<anonymous> (test\index.js:55:41)
    at processImmediate (internal/timers.js:439:21)]]></failure>
    </testcase>
  </testsuite>
  <testsuite name="Admin" timestamp="2021-11-06T12:36:46" tests="7" file="C:\Users\artio\Desktop\6 Classes\8.2.classes\test\index.js" time="0.0020" failures="1">
    <testcase name="Admin should have method getArray" time="0.0000" classname="should have method getArray">
    </testcase>
    <testcase name="Admin should return instance of Guest as a first element by the method getArray" time="0.0000" classname="should return instance of Guest as a first element by the method getArray">
    </testcase>
    <testcase name="Admin should return instance of User as a third element by the method getArray" time="0.0000" classname="should return instance of User as a third element by the method getArray">
    </testcase>
    <testcase name="Admin should return array of roles by the method getArray" time="0.0010" classname="should return array of roles by the method getArray">
    </testcase>
    <testcase name="Admin should change type of role from Guest to User" time="0.0000" classname="should change type of role from Guest to User">
      <failure message="expected false to equal true" type="AssertionError"><![CDATA[AssertionError: expected false to equal true
    at Context.<anonymous> (test\index.js:84:56)
    at processImmediate (internal/timers.js:439:21)]]></failure>
    </testcase>
    <testcase name="Admin should change type of role from User to Guest" time="0.0000" classname="should change type of role from User to Guest">
    </testcase>
    <testcase name="Admin should move tasks from Guest to User, when change role" time="0.0000" classname="should move tasks from Guest to User, when change role">
    </testcase>
  </testsuite>
</testsuites>

【问题讨论】:

你为什么期望guest.createTask 抛出?当您访问不存在的对象的属性时,JS 的行为一直是返回undefined。如果您尝试实际调用该方法,您会得到一个异常,但您没有这样做 是的,我明白了,但我认为我应该得到一个参考错误,即 createTask 未定义或如何调用该错误。 "expect(guest.createTask).to.throw('方法\'createTask\'未定义');" 不,你不应该——这不是 JS 的工作方式。它返回undefined,这是语言标准定义它的方式 再次,您希望抛出的错误消息不存在。因此,断言将失败。而且我真的不知道为什么你想要一个依赖特定错误消息的脆弱代码,而不是直接测试给定属性不是方法(或测试它不存在)。 如果你想专门依赖那些错误信息,那么你可以在Guest中添加createTask方法,让它抛出一个与错误信息匹配的错误断言。如果您不想真正修复它以使其正确,这是使此代码正常工作的唯一方法。 【参考方案1】:

这是我如何完成这项任务的,一点也不难,但令人困惑:

class Task 
    constructor(name) 
        this.name = name;
    

class Guest 
    constructor(tasks) 
        this.tasks = tasks;
    
    getTask(index) 
        return this.tasks[index];
    
    createTask() 
        throw new Error("method 'createTask' is not defined");
    
    changeType() 
        throw new Error("method 'changeType' is not defined");
    


class User 
    constructor(tasks) 
        this.tasks = tasks;
    
    getTask(index) 
        return this.tasks[index];
    
    createTask(tasks) 
        return this.tasks.push(tasks);
    
    changeType() 
        throw new Error("method 'changeType' is not defined");
    


class Admin 
    constructor(userGuestArray) 
        this.userGuestArray = userGuestArray;
    
    getArray() 
        return this.userGuestArray;
    

    changeType(index) 
       let mainArray = this.userGuestArray;
       let arr = this.userGuestArray[index];
        if (mainArray[index] instanceof Guest) 
            mainArray[index] = new User(arr.tasks);

         else if (mainArray[index] instanceof User) 
            mainArray[index] = new Guest(arr.tasks);
        
        return mainArray;
    

module.exports.Task = Task;
module.exports.Guest = Guest;
module.exports.User = User;
module.exports.Admin = Admin;

对于错误部分,我应该只抛出一个,这就是为什么我在测试时遇到错误,消息是我应该抛出一个错误

【讨论】:

以上是关于使用类创建角色的 JavaScript 功能的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript原型链

JavaScript实现类的privateprotectedpublicstatic以及继承

JavaScript继承与聚合

为什么我应该使用箭头函数而不是类或对象构造函数?

设计模式之装饰模式

建造者模式