字符串拼接引發(fā)的BUG

譯者按: bug雖小,卻是個(gè)磨人的小妖精!

為了保證可讀性,本文采用意譯而非直譯。另外,本文版權(quán)歸原作者所有,翻譯僅用于學(xué)習(xí)。

這是一篇很簡短的博客,記錄了我今天早上花了一個(gè)小時(shí)才解掉的一個(gè)bug。

準(zhǔn)備工作

在已有的網(wǎng)站頁面,我們已經(jīng)有一段JavaScript代碼用于構(gòu)建字符串并把它插入到DOM中,如下所示:

function GetTemplate(url, html)  
{
   // 省掉部分細(xì)節(jié)代碼
   // ...
   var template = '<div class="something"><a href="'
                  + url
                  + '" target="_blank"><strong>Details: </strong><span>'
                  + html
                  + '</span></a></div>';
  return template;
}

請(qǐng)忽略這段代碼的粗糙。接下來,我們的需求很簡單:如果summary存在,那么在<strong>標(biāo)簽前面添加一個(gè)額外的<span>標(biāo)簽將該值顯示出來。是不是很簡單?我們來試一試。

首次嘗試

我快速實(shí)現(xiàn)了如下代碼:

function GetTemplate(url, html, summary) {  
   // other details removed
   var template = '<div class="something"><a href="'
                  + url
                  + '" target="_blank">';

   if(summary) {
       template += '<span class="summary">' 
           + summary 
           + '</span>';
   }

   template +=
       +'<strong>Details: </strong><span>'
       + html
       + '</span></a></div>';

  return template;
}

看上去一切OK,沒有問題。F5刷新頁面,看起來不大對(duì):

first_try_fail.png

你知道哪里出問題了嗎?

由上面的代碼生成的HTML長這樣:

<div class="something"><a  target="blank">  
    <span class="summary">The summary</span>NaNThis is the inner message</span></a>
</div>  

發(fā)現(xiàn)問題了嗎?如果沒發(fā)現(xiàn),我們接著往下看。

你的線上代碼真的沒有BUG嗎?歡迎免費(fèi)使用Fundebug!我們可以幫助您第一時(shí)間發(fā)現(xiàn)BUG!

字符串拼接 vs 加法

仔細(xì)查看生成的HTML代碼,你會(huì)發(fā)現(xiàn)NaN出現(xiàn)在</span>標(biāo)記的后面,然而<strong>標(biāo)簽不見了。NaN是一個(gè)很好的線索,表明這里有類型轉(zhuǎn)換發(fā)生,并且是轉(zhuǎn)換為Number類型,但是我當(dāng)時(shí)一直沒有找到發(fā)生轉(zhuǎn)換的原因!

接下來,我們先溫習(xí)一下JavaScript基礎(chǔ)知識(shí)。在JavaScript中,根據(jù)+左右兩邊變量的類型的不同,+符號(hào)可以用于數(shù)字相加或則字符串拼接。

console.log('value:' + 3);           // 'value:3'  
console.log(3 + 1);                   // 4  
console.log('value:' + 3 + '+' + 1); // 'value:3+1'  
console.log('value:' + 3 + 1);       // 'value:31'  
console.log('value:' + (3 + 1));     // 'value:4'  
console.log(3 + ' is the value');    // '3 is the value'  

在上面的這些例子中,如果+的任何一邊是字符串,那么另一邊一定會(huì)轉(zhuǎn)換為字符串。否則,將看做是數(shù)字相加。

因此,NaN預(yù)示著一定是字符串被誤用為數(shù)字了。但我并沒有使用parseInt()函數(shù)做類型轉(zhuǎn)換,所以邏輯上說不通??!

問題原因

最終,我逐步縮小出錯(cuò)區(qū)域,發(fā)現(xiàn)是如下代碼出錯(cuò):

template +=  
       +'<strong>Details: </strong><span>'
       + html
       + '</span></a></div>';

如果你還是沒看出來,那么我們換個(gè)寫法:

template += +'<strong>Details: </strong><span>' + html + '</span></a></div>';  

我用了string += +string這樣的寫法,也就是說:由于寫代碼的時(shí)候拷貝黏貼,不小心整了一個(gè)多余的+號(hào)?所以,相當(dāng)于使用了一元運(yùn)算+。根據(jù)一元運(yùn)算符(+)的官方解釋:+c會(huì)顯示地將c轉(zhuǎn)換為Number類型。

這就是我的代碼出現(xiàn)bug的根源:一元運(yùn)算符+號(hào)嘗試將<strong>Details: </strong><span>轉(zhuǎn)換為數(shù)字,但是失敗了返回NaN。然后NaN又轉(zhuǎn)換為字符串拼接起來。當(dāng)我把這個(gè)額外的+刪掉后,代碼就正確運(yùn)行了。

額外建議

另外值得一提的是,我使用了gulp-uglify來壓縮我的JavaScript代碼。在構(gòu)建過程中,一元運(yùn)算(+'<strong>Details: </strong><span>')已經(jīng)在壓縮后的代碼中存儲(chǔ)為NaN了。Gulp已經(jīng)識(shí)別出代碼錯(cuò)誤。

從這一次Debug的經(jīng)歷吸取了一個(gè)教訓(xùn):不要馬馬虎虎的拷貝黏貼代碼!而且我立即想到如果有一個(gè)小的gulp插件可以識(shí)別并提醒壓縮代碼中有莫名其妙的NaN的話,也可以適當(dāng)避免問題。

補(bǔ)充

> parseInt('<strong>Details: </strong><span>')
NaN
> +'<strong>Details: </strong><span>'
NaN


版權(quán)聲明:
轉(zhuǎn)載時(shí)請(qǐng)注明作者Fundebug以及本文地址:
https://blog.fundebug.com/2017/11/20/bug-fix-concatenated-string-trun-into-numbers/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本文純屬原創(chuàng)? 如有雷同? 純屬抄襲? 不甚榮幸! 歡迎轉(zhuǎn)載! 原文收錄在【我的GitHub博客】,覺得本文...
    微醺歲月閱讀 2,156評(píng)論 2 11
  • 值類型轉(zhuǎn)換將值從一種類型轉(zhuǎn)換為另一種類型通常稱為類型轉(zhuǎn)換,這是顯示的情況;隱式的情況稱為強(qiáng)制類型轉(zhuǎn)換。JavaSc...
    xpwei閱讀 3,727評(píng)論 0 5
  • 第5章 引用類型(返回首頁) 本章內(nèi)容 使用對(duì)象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學(xué)一百閱讀 3,663評(píng)論 0 4
  • 1.面試:面試不容易啊 2.入職:學(xué)習(xí)才剛剛開始 3.培訓(xùn):理論 4.技能:英文名字,動(dòng)手 5.神話:神話都是從凡...
    依米花1993閱讀 801評(píng)論 0 1
  • 關(guān)于作者 諾特伯格,瑞典人。他不是番茄工作法的發(fā)明者,而是番茄工作法的深度愛好者和實(shí)踐者。 關(guān)于本書 本書介紹了時(shí)...
    大S小J閱讀 303評(píng)論 0 1

友情鏈接更多精彩內(nèi)容