在 Spotify 播放列表应用程序中添加和删除曲目

Adding and removing tracks from a Spotify playlist app

我目前正在完成一个项目,我必须在其中构建一个 Spotify 播放列表创建器。为此,我需要在播放列表中添加或删除曲目。我编写了一个看起来可行的方法,但它与官方解决方案不同,所以我只是想看看是否有理由不按我的方式去做。

具体来说,他们在我使用 .includes 的地方使用 .find 和 .filter 方法。我所做的有缺点吗?

他们的代码

addTrack(track) {
    let tracks = this.state.playlistTracks;
    if (tracks.find(savedTrack => savedTrack.id === track.id)) {
      return;
    }

    tracks.push(track);
    this.setState({ playlistTracks: tracks});
}

removeTrack(track) {
    let tracks = this.state.playlistTracks;
    tracks = tracks.filter(currentTrack => currentTrack.id !== track.id);

    this.setState({playlistTracks: tracks});
}

我的代码

addTrack(track) {
   let tracks = this.state.playlistTracks;
   if (!tracks.includes(track)) {
      tracks.push(track);
   }
   this.setState({playlistTracks: tracks});
}

removeTrack(track) {
   let tracks = this.state.playlistTracks;
   if (tracks.includes(track)) {
     let index = tracks.indexOf(track);
     tracks.splice(index, 1);
   }
   this.setState({playlistTracks: tracks});
}

问题与引用有关,您已对 playlistTracks

进行了另一个引用
addTrack(track) {
   let { playlistTracks } = this.state;
   let tracks = [...playlistTracks];
   if (!tracks.includes(track)) {
      tracks.push(track);
   }
   this.setState({ playlistTracks: tracks });
}

removeTrack(track) {
   let { playlistTracks } = this.state;
   let tracks = [...playlistTracks];
   if (tracks.includes(track)) {
     let index = tracks.indexOf(track);
     tracks.splice(index, 1);
   }
   this.setState({ playlistTracks: tracks });
}

我的建议

addTrack(track) {
   const { playlistTracks } = this.state;
   const tracks = [...playlistTracks];
   const index = tracks.indexOf(track);
   if (index < 0) {
      tracks.push(track);
   }
   this.setState({ playlistTracks: tracks });
}

removeTrack(track) {
   const { playlistTracks } = this.state;
   const tracks = [...playlistTracks];
   const index = tracks.indexOf(track);
   if (index > -1) {
     tracks.splice(index, 1);
   }
   this.setState({ playlistTracks: tracks });
}


是的,有一个显着的区别,因为 includes() 只会 return true 如果你传递给它实际的实例(我的意思是指向相同的引用对象)您正在寻找的曲目。

所提供的解决方案仅根据曲目 ID 比较曲目,因此有所不同。

参见以下示例:

const tracks = [
  {id: 1, title: "mysong1"},
  {id: 2, title: "mysong2"},
] 

function isTrackPresentIncludes(track){
  return tracks.includes(track);
}

function isTrackPresentFind(track){
  return tracks.find(it => it.id === track.id) !== undefined;
}


// this will be true
console.log("with includes(tracks[0]):\n", isTrackPresentIncludes(tracks[0]))
// this will be false as it's a different object
console.log("with includes({id: 1, title: \"mysong1\"}):\n", isTrackPresentIncludes({id: 1, title: "mysong1"}))

// this will be true
console.log("with find(tracks[0]):\n", isTrackPresentFind(tracks[0]))
// this will also be true
console.log("with find({id: 1, title: \"mysong1\"}):\n", isTrackPresentFind({id: 1, title: "mysong1"}))

您的 removeTrack() 中的 indexOf() 也有同样的问题。

还有一点我不太喜欢这个解决方案。 find() returns 找到的曲目,但 return 值从未实际使用过,所以在我看来你应该使用 some() 而不是 returns truefalse.

我认为这不是问题,但如果数组包含 falsy 值,它可能会导致意外行为。 考虑一下:

const arrayWithFalsyValues = [
  0,  // zero is falsy!
  1, 
  2, 
  3, 
  4, 
  5, 
  6, 
  7, 
  8
] 

function isPresent(toBeFound){
  if(arrayWithFalsyValues.find(number => number === toBeFound)){
    console.log(`Value ${toBeFound} found in array`);
  }
  else{
    console.log(`Value ${toBeFound} NOT found in array`);
  }
}

console.log("Array:", arrayWithFalsyValues)
// this will work as expected
console.log("Contains 3?")
isPresent(3)
console.log("Contains 8?")
isPresent(8)
console.log("Contains 10?")
isPresent(10)
// now search for the falsy value -> incorrect result
console.log("Contains 0?")
isPresent(0)