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

使用扩展运算符时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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 23:45:36