javascript加号"+"的二义性说明


Posted in Javascript onMarch 04, 2013

单个的加号作为运算符在 JavaScript 中有三种作用。它可以表示字符串连接,例如:

var str = 'hello ' + 'world!';

或表示数字取正值的一元运算符,例如:

var n = 10;  
var n2 = +n;

或表示数值表达式的求和运算,例如:

var n = 100;  
var nn2 = n + 1; 
 

三种表示法里,字符串连接与数字求和是容易出现二义性的。因为 JavaScript 中对这两种运算的处理将依赖于数据类型,而无法从运算符上进行判读。我们单独地看一个表达式:

aa = a + b;

是根本无法知道它真实的含义是在求和,亦或是在做字符串连接。这在 JavaScript 引擎做语法分析时,也是无法确知的。

加号"+"带来的主要问题与另一条规则有关。这条规则是"如果表达式中存在字符串,则优先按字符串连接进行运算"。例如:

var v1 = '123';  
var v2 = 456;  //显示结果值为字符串'123456'  
alert( v1 + v2 );

这会在一些宿主中出现问题。例如浏览器中,由于 DOM 模型的许多值看起来是数字,但实际上却是字符串。因此试图做"和"运算,却变成了"字符串连接"运算。下面的例子说明了这个问题:

<img id="testPic" style="border: 1 solid red"> 
 

我们看到这个 id 为 testPic 的 IMG 元素(element)有一个宽度为 1 的边框--省略了默认的单位 px(pixel,像素点)。但是如果你试图用下面的代码来加宽它的边框,就会导致错误(一些浏览器忽略该值,另一些则弹出异常,还有一些浏览器则可能崩溃):

var el = document.getElementById('testPic');  
el.style.borderWidth += 10; 
 

因为事实上在 DOM 模型里,borderWidth 是有单位的字符串值,因此这里的值会是"1px"。JavaScript 本身并不会出错,它会完成类似下面的运算,并将值赋给 borderWidth:

el.style.borderWidth = '1px' + 10;  
//值为 '1px10'

这时,浏览器的 DOM 模型无法解释"1px10"的含义,因此出错了。当你再次读borderWidth 值时,它将仍是值 1px。那么,怎么证明上述的运算过程呢?下面的代码将表明 JavaScript 运算的结果是 1px10,但赋值到 borderWidth 时,是由于 DOM 忽略掉这个错误的值,因此 borderWidth 没有发生实际的修改:

alert( el.style.borderWidth = '1px' + 10 );//值为 '1px10'

这个问题追其根源,一方面在于我们允许了省略单位的样式表写法,另一方面也在于脚本引擎不能根据运算符来确定这里的操作是数值运算还是字符串连接。

后来 W3C 推动 XHTML 规范,试图从第一个方面来避免这个问题,但对开发界的影响仍旧有限。因此,在浏览器的开发商提供的手册中,都会尽可能地写明每一个属性的数据类型,以避免开发人员写出上面这样的代码。在这种情况下,最正确的写法是:

var el = document.getElementById('testPic');  
// 1.取原有的单位  
var value = parseInt(el.style.borderWidth);  
var unit = el.style.borderWidth.substr(value.toString().length);  
// 2.运算结果并附加单位  
el.style.borderWidth = value + 10 + unit;  //如果你确知属性采用了默认单位 px,并试图仍然省略单位值,  
//那么你可以用下面这种方法(我并不推荐这样):  
// el.style.borderWidth = parseInt(el.style.borderWidth) + 10;
Javascript 相关文章推荐
Date对象格式化函数代码
Jul 17 Javascript
模拟多级复选框效果的jquery代码
Aug 13 Javascript
jquery导航制件jquery鼠标经过变色效果示例
Dec 05 Javascript
js形成页面的一种遮罩效果实例代码
Jan 04 Javascript
javascript数据类型示例分享
Jan 19 Javascript
javascript实现图片循环渐显播放的方法
Feb 24 Javascript
jQuery网页右侧广告跟随滚动代码分享
Apr 20 Javascript
基于javascript实现checkbox复选框实例代码
Jan 28 Javascript
去除字符串左右两边的空格(实现代码)
May 12 Javascript
JS使用JSON作为参数实例分析
Jun 23 Javascript
详解windows下vue-cli及webpack 构建网站(三)使用组件
Jun 17 Javascript
详解Vue快速零配置的打包工具——parcel
Jan 16 Javascript
js给dropdownlist添加选项的小例子
Mar 04 #Javascript
jQuery侧边栏随窗口滚动实现方法
Mar 04 #Javascript
利用js实现选项卡的特别效果的实例
Mar 03 #Javascript
DWZ刷新dialog解决方法
Mar 03 #Javascript
js 控制下拉菜单刷新的方法
Mar 03 #Javascript
可在线编辑网页文字效果代码(单击)
Mar 02 #Javascript
javascript重复绑定事件造成的后果说明
Mar 02 #Javascript
You might like
PHP截取中文字符串的问题
2006/07/12 PHP
PHP 处理TXT文件(打开/关闭/检查/读取)
2013/05/13 PHP
php中创建和调用webservice接口示例
2014/07/25 PHP
老生常谈PHP面向对象之命令模式(必看篇)
2017/05/24 PHP
URI、URL和URN之间的区别与联系
2006/12/20 Javascript
JavaScript 编程引入命名空间的方法
2007/06/29 Javascript
javascript数组快速打乱重排的方法
2014/01/02 Javascript
js实现禁止中文输入的方法
2015/01/14 Javascript
在其他地方你学不到的jQuery小贴士和技巧(欢迎收藏)
2016/01/20 Javascript
jQuery实现的简单排序功能示例【冒泡排序】
2017/01/13 Javascript
原生js实现放大镜
2017/02/20 Javascript
JavaScript实现前端实时搜索功能
2020/03/26 Javascript
微信小程序滚动Tab实现左右可滑动切换
2017/08/17 Javascript
浅谈Koa服务限流方法实践
2017/10/23 Javascript
bootstrap tooltips在 angularJS中的使用方法
2019/04/10 Javascript
详解JavaScript 浮点数运算的精度问题
2019/07/23 Javascript
[05:53]完美世界携手游戏风云打造 卡尔工作室观战系统篇
2013/04/22 DOTA
[01:14:19]NAVI vs Mineski 2019国际邀请赛淘汰赛 败者组BO1 8.20.mp4
2020/07/19 DOTA
python中实现定制类的特殊方法总结
2014/09/28 Python
python正则表达式之对号入座篇
2018/07/24 Python
Python3.4 splinter(模拟填写表单)使用方法
2018/10/13 Python
python 处理string到hex脚本的方法
2018/10/26 Python
python验证身份证信息实例代码
2019/05/06 Python
8种用Python实现线性回归的方法对比详解
2019/07/10 Python
Hawes & Curtis澳大利亚官网:英国经典服饰品牌
2018/10/29 全球购物
存储过程的优缺点是什么
2015/01/10 面试题
初一家长会邀请函
2014/01/31 职场文书
《雨霖铃》教学反思
2014/02/22 职场文书
教育基金募捐倡议书
2014/05/14 职场文书
殡葬服务心得体会
2014/09/11 职场文书
三严三实对照检查材料
2014/09/22 职场文书
长城导游词400字
2015/01/30 职场文书
员工自我工作评价
2015/03/06 职场文书
女性健康知识讲座主持词
2015/07/04 职场文书
JS继承最简单的理解方式
2021/03/31 Javascript
ubuntu20.04虚拟机无法上网的问题及解决
2022/12/24 Servers