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 相关文章推荐
javascript之querySelector和querySelectorAll使用说明
Oct 09 Javascript
js 自制滚动条的小例子
Mar 16 Javascript
Javascript前端UI框架Kit使用指南之kitjs事件管理
Nov 28 Javascript
js实现可键盘控制的简单抽奖程序
Jul 13 Javascript
jQuery中ztree 点击文本框弹出下拉框的实例代码
Feb 05 Javascript
微信小程序 滚动到某个位置添加class效果实现代码
Apr 19 Javascript
详解AngularJS ui-sref的简单使用
Apr 24 Javascript
koa源码中promise的解读
Nov 13 Javascript
微信小程序常用简易小函数总结
Feb 01 Javascript
jqGrid表格底部汇总、合计行footerrow处理
Aug 21 Javascript
小程序使用watch监听数据变化的方法详解
Sep 20 Javascript
Javascript模拟实现new原理解析
Mar 03 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
绿山咖啡和蓝山咖啡
2021/03/04 新手入门
PHP网站备份程序代码分享
2011/06/10 PHP
PHP、Java des加密解密实例
2015/04/27 PHP
详解php协程知识点
2018/09/21 PHP
百度地图api应用标注地理位置信息(js版)
2013/02/01 Javascript
JQuery中form验证出错信息的查看方法
2013/10/08 Javascript
JS JQUERY实现滚动条自动滚到底的方法
2015/01/09 Javascript
javascript中关于&amp;&amp; 和 || 表达式的小技巧分享
2015/04/10 Javascript
jQuery form插件之ajaxForm()和ajaxSubmit()的可选参数项对象
2016/01/23 Javascript
AngularJS基础 ng-include 指令示例讲解
2016/08/01 Javascript
zTree异步加载展开第一级节点的实现方法
2017/09/05 Javascript
vue父组件向子组件(props)传递数据的方法
2018/01/02 Javascript
JavaScript中的回调函数实例讲解
2019/01/27 Javascript
微信小程序遍历Echarts图表实现多个饼图
2019/04/25 Javascript
高效jQuery选择器的5个技巧实例分析
2019/11/26 jQuery
videocapture库制作python视频高速传输程序
2013/12/23 Python
浅析Python编写函数装饰器
2016/03/18 Python
Python数据结构之双向链表的定义与使用方法示例
2018/01/16 Python
Python中多个数组行合并及列合并的方法总结
2018/04/12 Python
windows下python 3.6.4安装配置图文教程
2018/08/21 Python
python3转换code128条形码的方法
2019/04/17 Python
python3实现elasticsearch批量更新数据
2019/12/03 Python
如何在mac环境中用python处理protobuf
2019/12/25 Python
Skyscanner阿联酋:全球领先的旅游搜索平台
2017/11/25 全球购物
口腔医学技术应届生求职信
2013/11/09 职场文书
红领巾广播站广播稿
2014/02/01 职场文书
2014年辅导员工作总结
2014/11/18 职场文书
安全责任书
2015/01/29 职场文书
副总经理岗位职责范本
2015/04/08 职场文书
党支部培养考察意见
2015/06/02 职场文书
入党团支部推荐意见
2015/06/02 职场文书
就业证明函
2015/06/17 职场文书
运动会800米赞词
2015/07/22 职场文书
创业计划书之溜冰场
2019/10/25 职场文书
SpringBoot整合Mybatis Generator自动生成代码
2021/08/23 Java/Android
Nginx 路由转发和反向代理location配置实现
2021/11/11 Servers