使用扩展运算符时array.map()为何未返回新值?
问题分析与解决方案
1. 核心问题:books数组的对象结构完全错误
你的books数组里,除第一个对象外,其余对象都重复定义了id键,比如第二个对象:
{ id: 5, imageUrl: '', id: 6, title: 'Title:', id: 7, author: 'Author:', id: 8, pages: 'Pages:' }
在JavaScript中,对象的重复键会被最后一个值覆盖,所以这个对象实际的id是8,而非5/6/7。这直接导致你用map匹配id == 1时,只有第一个对象会被修改,其余对象因id不匹配原封不动返回。
正确的书籍数组结构应该是每个对象对应一本书:
const books = [ { id: 1, imageUrl: '', title: 'Title:', author: 'Author:', pages: 'Pages:' }, { id: 2, imageUrl: '', title: 'Title:', author: 'Author:', pages: 'Pages:' }, { id: 3, imageUrl: '', title: 'Title:', author: 'Author:', pages: 'Pages:' }, { id: 4, imageUrl: '', title: 'Title:', author: 'Author:', pages: 'Pages:' } ];
2. 需求偏差:你在修改已有书籍,而非添加新书籍
你的目标是添加新书籍到图书库,但当前用map是修改已有id=1的书籍,正确做法是创建新书籍对象,用扩展运算符将其加入新数组:
// 把渲染单个书籍的逻辑抽成函数,方便复用 function renderBook(book) { let booksDisplay = document.createElement('div') booksDisplay.setAttribute('class', 'booksDisplay') let booksDisplayImage = document.createElement('img'); booksDisplayImage.src = book.imageUrl; booksDisplayImage.setAttribute('class', 'booksImage'); let imageContainer = document.createElement('div') imageContainer.setAttribute('class', 'imageContainer'); booksDisplay.appendChild(imageContainer); imageContainer.appendChild(booksDisplayImage); let booksDisplayTextTitle = document.createElement('p'); booksDisplayTextTitle.setAttribute('class', 'titleText') booksDisplayTextTitle.textContent = book.title; let booksDisplayTextAuthor = document.createElement('p'); booksDisplayTextAuthor.setAttribute('class', 'authorText') booksDisplayTextAuthor.textContent = book.author; let booksDisplayTextPages = document.createElement('p'); booksDisplayTextPages.setAttribute('class', 'pagesText') booksDisplayTextPages.textContent = book.pages; let textContainer = document.createElement('div'); textContainer.setAttribute('class', 'textContainer'); booksDisplay.appendChild(textContainer); textContainer.appendChild(booksDisplayTextTitle); textContainer.appendChild(booksDisplayTextAuthor); textContainer.appendChild(booksDisplayTextPages); let buttonRead = document.createElement('button') buttonRead.textContent = 'I have read this book'; let buttonRemove = document.createElement('button'); buttonRemove.textContent = 'Remove a book'; buttonRemove.addEventListener('click', () => { booksDisplayTextTitle.textContent = 'Title:'; booksDisplayTextAuthor.textContent = 'Author:'; booksDisplayTextPages.textContent = 'Pages:'; booksDisplayImage.style.display = 'none'; imageContainer.style.border = '1px solid rgb(107, 107, 107)' }); textContainer.appendChild(buttonRead) textContainer.appendChild(buttonRemove) booksContainer.appendChild(booksDisplay); } // 初始化渲染已有书籍 books.forEach(book => renderBook(book)); // 确认添加新书籍的逻辑 buttonConfirm.addEventListener('click', () => { // 创建新书籍对象 const newBook = { id: Date.now(), // 用时间戳生成唯一id,避免重复 imageUrl: inputImageUrl.value, title: `Title: ${inputTitle.value}`, author: `Author: ${inputAuthor.value}`, pages: `Pages: ${inputPages.value}` }; // 生成包含新书籍的新数组 const newBooks = [...books, newBook]; console.log(newBooks); // 渲染新书籍到页面 renderBook(newBook); // 清空输入框 inputImageUrl.value = ''; inputTitle.value = ''; inputAuthor.value = ''; inputPages.value = ''; });
3. DOM选择器的局限性
你用document.querySelector('.titleText')只会选中页面上第一个匹配的元素,导致点击确认后只能修改第一本书的内容。抽离渲染函数后,新增书籍时单独渲染,就能避免这个问题。
内容的提问来源于stack exchange,提问作者madlib
相关产品推荐
相关产品推荐

