字符串拼接引发的BUG | Fundebug博客
source link: https://blog.fundebug.com/2017/11/20/bug-fix-concatenated-string-trun-into-numbers/?
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
字符串拼接引发的BUG
译者按: bug 虽小,却是个磨人的小妖精!
本文采用意译,版权归原作者所有
这是一篇很简短的博客,记录了我今天早上花了一个小时才解掉的一个 bug。
在已有的网站页面,我们已经有一段 JavaScript 代码用于构建字符串并把它插入到 DOM 中,如下所示:
function GetTemplate(url, html) {
// 省掉部分细节代码
// ...
var template =
'<div class="something"><a href="' +
url +
'" target="_blank"><strong>Details: </strong><span>' +
html +
"</span></a></div>";
return template;
}
请忽略这段代码的粗糙。接下来,我们的需求很简单:如果summary
存在,那么在<strong>
标签前面添加一个额外的<span>
标签将该值显示出来。是不是很简单?我们来试一试。
我快速实现了如下代码:
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
刷新页面,看起来不大对:
你知道哪里出问题了吗?
由上面的代码生成的 HTML 长这样:
<div class="something"><a href="https://thewebsite.com" target="blank">
<span class="summary">The summary</span>NaNThis is the inner message</span></a>
</div>
发现问题了吗?如果没发现,我们接着往下看。
你的线上代码真的没有 BUG 吗?欢迎免费使用Fundebug!我们可以帮助您第一时间发现 BUG!
字符串拼接 vs 加法
仔细查看生成的 HTML 代码,你会发现NaN
出现在</span>
标记的后面,然而<strong>
标签不见了。NaN
是一个很好的线索,表明这里有类型转换发生,并且是转换为 Number 类型,但是我当时一直没有找到发生转换的原因!
接下来,我们先温习一下 JavaScript 基础知识。在 JavaScript 中,根据+
左右两边变量的类型的不同,+
符号可以用于数字相加或则字符串拼接。
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'
在上面的这些例子中,如果+
的任何一边是字符串,那么另一边一定会转换为字符串。否则,将看做是数字相加。
因此,NaN
预示着一定是字符串被误用为数字了。但我并没有使用parseInt()
函数做类型转换,所以逻辑上说不通啊!
最终,我逐步缩小出错区域,发现是如下代码出错:
template += +"<strong>Details: </strong><span>" + html + "</span></a></div>";
如果你还是没看出来,那么我们换个写法:
template += +"<strong>Details: </strong><span>" + html + "</span></a></div>";
我用了string += +string
这样的写法,也就是说:由于写代码的时候拷贝黏贴,不小心整了一个多余的+
号?所以,相当于使用了一元运算+
。根据一元运算符(+
)的官方解释:+c
会显示地将c
转换为 Number 类型。
这就是我的代码出现 bug 的根源:一元运算符+
号尝试将<strong>Details: </strong><span>
转换为数字,但是失败了返回NaN
。然后NaN
又转换为字符串拼接起来。当我把这个额外的+
删掉后,代码就正确运行了。
另外值得一提的是,我使用了gulp-uglify
来压缩我的 JavaScript 代码。在构建过程中,一元运算(+'<strong>Details: </strong><span>'
)已经在压缩后的代码中存储为NaN
了。Gulp
已经识别出代码错误。
从这一次 Debug 的经历吸取了一个教训:不要马马虎虎的拷贝黏贴代码!而且我立即想到如果有一个小的gulp
插件可以识别并提醒压缩代码中有莫名其妙的NaN
的话,也可以适当避免问题。
> parseInt('<strong>Details: </strong><span>')
NaN
> +'<strong>Details: </strong><span>'
NaN
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK