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
相关产品推荐
相关产品推荐

