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 相关文章推荐
使用jquery实现的一个图片延迟加载插件(含图片延迟加载原理)
Jun 05 Javascript
Node.js中对通用模块的封装方法
Jun 06 Javascript
JS+CSS实现自动改变切换方向图片幻灯切换效果的方法
Mar 02 Javascript
BootStrap扔进Django里的方法详解
May 13 Javascript
利用jQuery插件imgAreaSelect实现图片上传裁剪(同步显示图像位置信息)
Dec 02 Javascript
jQuery实现两列等高并自适应高度
Dec 22 Javascript
使用snowfall.jquery.js实现爱心满屏飞的效果
Jan 05 Javascript
vue.js+Element实现表格里的增删改查
Jan 18 Javascript
bootstrap实现的自适应页面简单应用示例
Mar 09 Javascript
重新理解JavaScript的六种继承方式
Mar 24 Javascript
web前端页面生成exe可执行文件的方法
Feb 08 Javascript
vue2.0 使用element-ui里的upload组件实现图片预览效果方法
Sep 04 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
星际争霸兵种名称对照表
2020/03/04 星际争霸
让你的网站首页自动选择语言转跳
2006/12/06 PHP
PHP生成随机字符串(3种方法)
2015/09/25 PHP
Windows上php5.6操作mongodb数据库示例【配置、连接、获取实例】
2019/02/13 PHP
一个高效的JavaScript压缩工具下载集合
2007/03/06 Javascript
iframe 自适应高度[在IE6 IE7 FF下测试通过]
2009/04/13 Javascript
JavaScript实现网页上的浮动广告的简单方法
2013/06/14 Javascript
基于jquery扩展漂亮的下拉框可以二次修改
2013/11/19 Javascript
jQuery处理json数据返回数组和输出的方法
2015/03/11 Javascript
JavaScript中的this关键字使用方法总结
2015/03/13 Javascript
JavaScript电子时钟倒计时第二款
2016/01/10 Javascript
jQuery ajax请求struts action实现异步刷新
2017/04/19 jQuery
vue2.0 中#$emit,$on的使用详解
2017/06/07 Javascript
详解Angular 自定义结构指令
2017/06/21 Javascript
vue路由 遍历生成复数router-link的例子
2019/10/30 Javascript
vue基于better-scroll实现左右联动滑动页面
2020/06/30 Javascript
js编写简易的计算器
2020/07/29 Javascript
解决vue addRoutes不生效问题
2020/08/04 Javascript
举例讲解Django中数据模型访问外键值的方法
2015/07/21 Python
python 3.6 tkinter+urllib+json实现火车车次信息查询功能
2017/12/20 Python
python tkinter界面居中显示的方法
2018/10/11 Python
python读取TXT每行,并存到LIST中的方法
2018/10/26 Python
python实例化对象的具体方法
2020/06/17 Python
美国球鞋寄卖网站:Stadium Goods
2018/05/09 全球购物
公司薪酬管理制度
2014/01/31 职场文书
前厅收银主管岗位职责
2014/02/04 职场文书
军训自我鉴定怎么写
2014/02/13 职场文书
2014乡镇“三八”国际劳动妇女节活动总结
2014/03/01 职场文书
保护动物倡议书
2014/04/15 职场文书
优秀员工推荐信
2014/05/10 职场文书
银行委托书范本
2014/09/28 职场文书
办公室个人总结
2015/02/28 职场文书
建议书的格式及范文
2015/09/14 职场文书
一波干货,会议主持词开场白范文
2019/05/06 职场文书
mysql事务对效率的影响分析总结
2021/10/24 MySQL
浅谈css清除浮动(clearfix和clear)的用法
2023/05/21 HTML / CSS