You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ES6图书馆类库开发报错:Books类setter触发TypeError

解决Books类Setter中的Cannot set property 'undefined' of undefined错误

嘿,我一眼就看出你遇到的是ES6类开发里的常见坑——未初始化内部存储属性导致的报错。这个错误说明你的Books类books setter方法里,试图给一个根本不存在的属性赋值,或者操作了一个undefined的对象。

错误根源推测

结合你给出的代码片段和报错信息,大概率是你在Books类的constructor里没有提前声明用来存储书籍集合的内部属性(比如this._books),当setter试图访问它时,它还是undefined,自然会抛出这个错误。举个反例,错误的写法可能是这样:

class Books {
  // 没有constructor初始化this._books
  set books(newBooks) {
    // 这里this._books是undefined,调用push直接报错
    this._books.push(...newBooks);
  }
}

完整修复方案

我把你的四个类都整理成可运行的正确版本,你可以直接参考:

1. Book类(基础书籍模型)

class Book {
  constructor(title, author, isbn) {
    this.title = title;
    this.author = author;
    this.isbn = isbn;
  }
}

2. Books类(书籍集合,修复setter问题)

class Books {
  constructor() {
    // 关键!初始化内部存储数组,确保this._books不是undefined
    this._books = [];
  }

  // 正确的books setter:负责验证+赋值
  set books(newBooks) {
    // 先验证输入合法性
    if (!Array.isArray(newBooks)) {
      throw new TypeError('传入的必须是Book实例组成的数组');
    }
    // 替换内部集合(如果要追加的话,用this._books.push(...newBooks))
    this._books = [...newBooks];
  }

  // 配套getter:返回副本,防止外部直接修改内部数据
  get books() {
    return [...this._books];
  }

  // 可选:添加单本书籍的方法
  addBook(book) {
    if (book instanceof Book) {
      this._books.push(book);
    } else {
      throw new TypeError('必须传入Book实例');
    }
  }
}

3. WorkingHours类(营业时间管理)

class WorkingHours {
  constructor(open, close, lunchStart, lunchEnd) {
    this.open = open;       // 比如"09:00"
    this.close = close;     // 比如"18:00"
    this.lunchStart = lunchStart; // 比如"12:00"
    this.lunchEnd = lunchEnd;     // 比如"13:00"
  }

  // 可选:判断当前时间是否营业的方法
  isOpen(currentTime = new Date()) {
    const parseTime = time => parseFloat(time.replace(':', '.'));
    const currentHour = currentTime.getHours() + currentTime.getMinutes()/60;
    
    const openHour = parseTime(this.open);
    const closeHour = parseTime(this.close);
    const lunchStartHour = parseTime(this.lunchStart);
    const lunchEndHour = parseTime(this.lunchEnd);

    return (currentHour >= openHour && currentHour < lunchStartHour) || 
           (currentHour >= lunchEndHour && currentHour < closeHour);
  }
}

4. Library类(主类整合所有功能)

class Library {
  constructor(name, workingHours) {
    this.name = name;
    this.workingHours = workingHours;
    this.booksCollection = new Books();
  }

  // 批量添加书籍
  setBooks(newBooks) {
    this.booksCollection.books = newBooks;
  }

  // 添加单本书籍
  addBook(book) {
    this.booksCollection.addBook(book);
  }

  // 获取所有书籍
  getAllBooks() {
    return this.booksCollection.books;
  }
}

测试运行代码

你可以用这段代码验证修复效果:

// 创建营业时间
const cityLibHours = new WorkingHours("09:00", "18:00", "12:00", "13:00");
// 创建图书馆实例
const cityLibrary = new Library("城市中央图书馆", cityLibHours);
// 创建书籍
const gatsby = new Book("了不起的盖茨比", "F·斯科特·菲茨杰拉德", "9780743273565");
const nineteenEightyFour = new Book("1984", "乔治·奥威尔", "9780451524935");
// 添加书籍
cityLibrary.setBooks([gatsby, nineteenEightyFour]);
cityLibrary.addBook(new Book("百年孤独", "加西亚·马尔克斯", "9787544258645"));
// 打印所有书籍
console.log(cityLibrary.getAllBooks());

关键注意事项

  • 初始化优先:类的所有内部状态属性,一定要在constructor里提前初始化,避免undefined的情况。
  • setter做验证:不要让setter直接赋值,先验证输入类型和合法性,防止脏数据进入。
  • 封装内部状态:getter返回内部数组的副本(用[...]扩展运算符),避免外部代码直接修改类的私有数据。

内容的提问来源于stack exchange,提问作者martini21

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:53:43