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 Select标记中options操作方法集合
Oct 22 Javascript
jquery+json 通用三级联动下拉列表
Apr 19 Javascript
写js时遇到的一些小问题
Dec 06 Javascript
原生js实现日期联动
Jan 12 Javascript
同步文本框内容JS代码实现
Aug 04 Javascript
js实现碰撞检测特效代码分享
Oct 16 Javascript
基于Vue实现电商SKU组合算法问题
May 29 Javascript
vue使用swiper.js重叠轮播组建样式
Nov 14 Javascript
jquery实现商品sku多属性选择功能(商品详情页)
Dec 20 jQuery
详解微信小程序工程化探索之webpack实战
Apr 20 Javascript
JavaScript 空间坐标的使用
Aug 19 Javascript
vue项目打包为APP,静态资源正常显示,但API请求不到数据的操作
Sep 12 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 连接mysql连接被重置的解决方法
2011/02/15 PHP
php对文件进行hash运算的方法
2015/04/03 PHP
基于php实现随机合并数组并排序(原排序)
2015/11/26 PHP
php版微信开发Token验证失败或请求URL超时问题的解决方法
2016/09/23 PHP
yii2使用GridView实现数据全选及批量删除按钮示例
2017/03/01 PHP
另一个javascript小测验(代码集合)
2011/07/27 Javascript
javascript制作幻灯片(360度全景图片)
2015/07/28 Javascript
QQ登录背景闪动效果附效果演示源码下载
2015/09/22 Javascript
jQuery的层级查找方式分析
2016/06/16 Javascript
JS扩展类,克隆对象与混合类实例分析
2016/11/26 Javascript
BootStrap学习笔记之nav导航栏和面包屑导航
2017/01/03 Javascript
BootStrap 弹出层代码
2017/02/09 Javascript
javascript实现动态显示颜色块的报表效果
2017/04/10 Javascript
JQuery 获取多个select标签option的text内容(实例)
2017/09/07 jQuery
微信小程序实现获取用户信息并存入数据库操作示例
2019/05/07 Javascript
jQuery实现颜色打字机的完整代码
2020/03/19 jQuery
[03:08]Ti4观战指南上
2014/07/07 DOTA
[41:21]夜魇凡尔赛茶话会 第三期02:看图识人
2021/03/11 DOTA
python和shell变量互相传递的几种方法
2013/11/20 Python
Python3编程实现获取阿里云ECS实例及监控的方法
2017/08/18 Python
python音频处理用到的操作的示例代码
2017/10/27 Python
python中文编码与json中文输出问题详解
2018/08/24 Python
pycharm 配置远程解释器的方法
2018/10/28 Python
用python生成(动态彩色)二维码的方法(使用myqr库实现)
2019/06/24 Python
深入浅析python3中的unicode和bytes问题
2019/07/03 Python
python函数修饰符@的使用方法解析
2019/09/02 Python
解决Django响应JsonResponse返回json格式数据报错问题
2020/08/09 Python
详解python 条件语句和while循环的实例代码
2020/12/28 Python
Mio Skincare法国官网:身体紧致及孕期身体护理
2018/04/04 全球购物
英国手机壳购买网站:Case Hut
2019/04/11 全球购物
Michael Kors香港官网:美国奢侈品品牌
2019/12/26 全球购物
P D PAOLA法国官网:西班牙著名的珠宝首饰品牌
2020/02/15 全球购物
酒店个人求职信范文
2014/01/25 职场文书
校庆团日活动总结
2014/08/28 职场文书
教师自我剖析材料(四风问题)
2014/09/30 职场文书
Python 实现绘制子图及子图刻度的变换等问题
2021/05/31 Python