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 相关文章推荐
免费空间广告万能消除代码
Sep 04 Javascript
DOM下的节点属性和操作小结
May 14 Javascript
来自国外的30个基于jquery的Web下拉菜单
Jun 22 Javascript
jquery实现页面图片等比例放大缩小功能
Feb 12 Javascript
js插件设置innerHTML时在IE8下提示“未知运行时错误”解决方法
Apr 25 Javascript
js简单时间比较的方法
Aug 02 Javascript
JS封装的选项卡TAB切换效果示例
Sep 20 Javascript
BootStrap Table 获取同行不同列元素的方法
Dec 19 Javascript
老生常谈jacascript DOM节点获取
Apr 17 Javascript
ES6使用Set数据结构实现数组的交集、并集、差集功能示例
Oct 31 Javascript
javascript显示动态时间的方法汇总
Jul 06 Javascript
JavaScript实现拖拽和缩放效果
Aug 24 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 和 HTML
2006/10/09 PHP
PHP开发过程中常用函数收藏
2009/12/14 PHP
深入PHP获取随机数字和字母的方法详解
2013/06/06 PHP
php中curl、fsocket、file_get_content三个函数的使用比较
2014/05/09 PHP
php 模拟 asp.net webFrom 按钮提交事件实例
2014/10/13 PHP
PHP判断IP并转跳到相应城市分站的方法
2015/03/25 PHP
Referer原理与图片防盗链实现方法详解
2019/07/03 PHP
jquery选择器之属性过滤选择器详解
2014/01/27 Javascript
让table变成exls的示例代码
2014/03/24 Javascript
node.js中的fs.symlinkSync方法使用说明
2014/12/15 Javascript
Vuejs第十篇之vuejs父子组件通信
2016/09/06 Javascript
jquery中绑定事件的异同
2017/02/28 Javascript
JavaScript实现审核流程状态的动态显示进度条
2017/03/15 Javascript
详解Vue 事件驱动和依赖追踪
2017/04/22 Javascript
微信小程序 新建登录页并实现tabBar隐藏
2017/06/13 Javascript
详解在 Angular 项目中添加 clean-blog 模板
2017/07/04 Javascript
js HTML5 canvas绘制图片的方法
2017/09/08 Javascript
JS猜数字游戏实例讲解
2020/06/30 Javascript
详解vue v-model
2020/08/31 Javascript
js实现日历
2020/11/07 Javascript
Python进阶学习之特殊方法实例详析
2017/12/01 Python
python绘制简单折线图代码示例
2017/12/19 Python
Python爬虫工程师面试问题总结
2018/03/22 Python
利用Python读取txt文档的方法讲解
2018/06/23 Python
浅析python内置模块collections
2019/11/15 Python
Python字符串对齐、删除字符串不需要的内容以及格式化打印字符
2021/01/23 Python
elf彩妆英国官网:e.l.f. Cosmetics英国(美国平价彩妆品牌)
2017/11/02 全球购物
allbeauty美国:英国在线美容店
2019/03/11 全球购物
衰败城市英国官网:Urban Decay英国
2020/04/29 全球购物
C语言基础笔试题
2013/04/27 面试题
什么是网络协议
2016/04/07 面试题
能否解释一下XSS cookie盗窃是什么意思
2012/06/02 面试题
高中生物教学反思
2014/02/05 职场文书
公司保洁员管理制度
2015/08/04 职场文书
Python Flask请求扩展与中间件相关知识总结
2021/06/11 Python
关于Nginx中虚拟主机的一些冷门知识小结
2022/03/03 Servers