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 相关文章推荐
提高 DHTML 页面性能
Dec 25 Javascript
理解Javascript_03_javascript全局观
Oct 11 Javascript
解决IE6的PNG透明JS插件使用介绍
Apr 17 Javascript
用JS将搜索的关键字高亮显示实现代码
Nov 08 Javascript
js图片预加载示例
Apr 30 Javascript
自己封装的常用javascript函数分享
Jan 07 Javascript
JS时间特效最常用的三款
Aug 19 Javascript
js为什么不能正确处理小数运算?
Dec 29 Javascript
AngularJS控制器之间的数据共享及通信详解
Aug 01 Javascript
vue-router实现webApp切换页面动画效果代码
May 25 Javascript
浅谈Angular6的服务和依赖注入
Jun 27 Javascript
react 中父组件与子组件双向绑定问题
May 20 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
WordPress判断用户是否登录的代码
2011/03/17 PHP
用php实现百度网盘图片直链的代码分享
2012/11/01 PHP
php配置php-fpm启动参数及配置详解
2013/11/04 PHP
php生成随机颜色的方法
2014/11/13 PHP
php+mysqli使用预处理技术进行数据库查询的方法
2015/01/28 PHP
php爬取天猫和淘宝商品数据
2018/02/23 PHP
js屏蔽鼠标键盘(右键/Ctrl+N/Shift+F10/F11/F5刷新/退格键)
2013/01/24 Javascript
jQuery的缓存机制浅析
2014/06/07 Javascript
jquery实现标签支持图文排列带上下箭头按钮的选项卡
2015/03/14 Javascript
JS动态修改iframe高度和宽度的方法
2015/04/01 Javascript
JS实现从顶部下拉显示的带动画QQ客服特效代码
2015/10/24 Javascript
JS模拟简易滚动条效果代码(附demo源码)
2016/04/05 Javascript
jQuery实现页面点击后退弹出提示框的方法
2016/08/24 Javascript
谈谈JavaScript的New关键字
2016/08/26 Javascript
通过扫描二维码打开app的实现代码
2016/11/10 Javascript
Javascript 闭包详解及实例代码
2016/11/30 Javascript
JS 实现计算器详解及实例代码(一)
2017/01/08 Javascript
小程序实现发表评论功能
2018/07/06 Javascript
Vue组件为什么data必须是一个函数
2020/06/11 Javascript
js实现弹窗效果
2020/08/09 Javascript
python3图片转换二进制存入mysql
2013/12/06 Python
总结用Pdb库调试Python的方式及常用的命令
2016/08/18 Python
apache部署python程序出现503错误的解决方法
2017/07/24 Python
python实现一个简单的并查集的示例代码
2018/03/19 Python
解决安装python库时windows error5 报错的问题
2018/10/21 Python
Linux下通过python获取本机ip方法示例
2019/09/06 Python
Django 简单实现分页与搜索功能的示例代码
2019/11/07 Python
python中查看.db文件中表格的名字及表格中的字段操作
2020/07/07 Python
详解Python中第三方库Faker
2020/09/25 Python
Gucci法国官方网站:意大利奢侈品牌
2018/07/25 全球购物
印尼网上商店:Alfacart.com
2019/03/11 全球购物
大学四年个人自我小结
2014/03/05 职场文书
领导干部廉政自律承诺书
2014/05/26 职场文书
工作失误检讨书范文
2015/01/26 职场文书
《最终幻想14》6.01版本4月5日推出 追加新任务新道具
2022/04/03 其他游戏
vue @ ~ 相对路径 路径别名设置方式
2022/06/05 Vue.js