【記錄】從優(yōu)化一段JS代碼暴露出的問題

今天趁空閑時間,讓同事優(yōu)化一段之前匆忙寫的代碼(主要優(yōu)化寫法問題)。在優(yōu)化過程中暴露出了一些很小,但很嚴重的問題。在此記下,以作警示。


下面一段是本次需要優(yōu)化的代碼

function initSubmitData() {
  for (let i = 0 i < this.exam.length i++) {
    this.submitData[i] = []
    for (let j = 0 j < this.exam[i].topicList.length j++) {
      if (this.exam[i].topicList[j].topicAttachment && typeof this.exam[i].topicList[j].topicAttachment === 'string') {
        this.exam[i].topicList[j].topicAttachment = JSON.parse(this.exam[i].topicList[j].topicAttachment)
      }

      if (this.exam[i].topicList[j].topicOption && typeof this.exam[i].topicList[j].topicOption === 'string') {
        this.exam[i].topicList[j].topicOption = JSON.parse(this.exam[i].topicList[j].topicOption)
      }

      let content = this.exam[i].topicList[j]

      this.submitData[i][j] = {
        topicId: content.topicID,
        topicTypeId: content.topicType,
        paperTopicScore: content.topicScore,
        standardAudio: content.topicAttachment.length > 0 ? Config.res + content.topicAttachment[0].attachmentUrl : '',
        standardAnswer: '',
        myAnswer: '',
        isAudio: false,
        audioAnswerList: []
      }

      if (Object.prototype.toString.call(content.topicOption) === '[object Array]') {
        for (let k = 0 k < content.topicOption.length k++) {
          this.submitData[i][j].audioAnswerList[k] = {
            coreType: '',
            score: '',
            audioUrl: '',
            standardAudio: '',
            recordId: '',
            attributes: ''
          }
        }
      } else {
        this.submitData[i][j].audioAnswerList[0] = {
          coreType: '',
          score: '',
          audioUrl: '',
          standardAudio: '',
          recordId: '',
          attributes: ''
        }
      }
    }
  }
}

下面是改寫中的重災(zāi)區(qū):

/*
 * 這是每個人都會提取出來的變量
 */
let _def = {
  coreType: '',
  score: '',
  audioUrl: '',
  standardAudio: '',
  recordId: '',
  attributes: ''
}

/*
 * 下面就是重災(zāi)區(qū)了
 */
for ( ... ) {
  someObj.array.push(_def)
}

這樣單獨列出來之后,問題在哪,想必各位一目了然了。但事實上,在整個代碼里面,一旦不留意,就很容易發(fā)生這種 傳值傳址 的問題,當(dāng)發(fā)生bug,調(diào)試的時候還不容易發(fā)現(xiàn)。

下面還有個錯誤寫法

// 接上面一段代碼
// ...
someObj.array = someObj.array.concat([])

這個錯誤的是對 concat 方法的理解不全面,concat 方法是 淺拷貝(shallow copy),雖然會生成一個新的數(shù)組,但數(shù)組里面的 該是 地址 的還是 地址 ,就好比狼已經(jīng)入室了,這時候再關(guān)門,為時已晚。

最后放出一段優(yōu)化過的代碼(也許還能優(yōu)化,歡迎提出)

function initSubmitData() {
  const _default = {
    coreType: '',
    score: '',
    audioUrl: '',
    standardAudio: '',
    recordId: '',
    attributes: ''
  }

  for (let i = 0; i < this.exam.length; i++) {
    this.submitData[i] = []
    for (let j = 0; j < this.exam[i].topicList.length; j++) {
      let content = this.exam[i].topicList[j]
      let topicAttachment = content.topicAttachment
      let topicOption = content.topicOption

      typeof topicAttachment === 'string' && (content.topicAttachment = JSON.parse(topicAttachment))
      typeof topicOption === 'string' && (content.topicOption = JSON.parse(topicOption))

      let oData = this.submitData[i][j] = {
        topicId: content.topicID,
        topicTypeId: content.topicType,
        paperTopicScore: content.topicScore,
        standardAudio: topicAttachment.length ? Config.res + topicAttachment[0].attachmentUrl : '',
        standardAnswer: '',
        myAnswer: '',
        isAudio: false,
        audioAnswerList: []
      }

      const array = topicOption instanceof Array ? topicOption : [1]

      for (let k = 0; k < array.length; k++) {
        oData.audioAnswerList[k] = Object.assign({}, _default)
      }
    }
  }
}

最后,我同事問我,這種優(yōu)化代碼有意思嗎?我覺得,這是培養(yǎng)一種碼代碼的習(xí)慣,好的編碼習(xí)慣益處多多,在此就不累述了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容