Javascript中的陷阱大集合【译】
昨天晚上在自己的个人技术博客上翻译了一篇有关Javascript的文章,今天想想还是把它投稿到博客园吧,大家可以一起看看,第一次翻译技术文章表示压力很大,呵呵,有不足的地方请指出。
写在最前面
这篇英文来自codeproject,原文A Collection of JavaScript Gotchas。我看了以后颇受启发,就把他翻译过来了,呵呵,第一次翻译这么长的技术文章,有什么错误请大家指出哦。另外,译文允许转载,但请在页面明显处标明以下信息:
英文原文:A Collection of JavaScript Gotchas
译文作者:王易做图
译文标题:Javascript中的陷阱大集合【译】
译文链接:http://www.itivy.com/ivy/archive/2011/11/13/my-javascript-gotchas.html
谢谢合作!
本文主要介绍怪异的Javascript,毋庸置疑,它绝对有怪异的一面。当软件开发者开始使用世界上使用最广泛的语言编写代码时,他们会在这个过 程中发现很多有趣的“特性”。即便是老练的Javascript开发者也可以在本文找到一些有趣的新陷阱,请留意这些陷阱,当然也可以尽情享受由这些陷阱 带来的“乐趣”!
函数和操作符
双等号
==操作符比较时会进行类型的强制转换,这意味着它可以比较两个不同类型的对象,在执行比较之前它将会尝试把这两个对象转换成同一个类型,举一个例子:
"1" == 1 //true
然而,这样往往会误导我们,而且我们也不需要这样子来比较。在上面的例子中,我们完全可以先将字符串转换成数字型,然后利用对类型敏感的三重等号(===)来进行比较,如:
Number("1") === 1; //true
或者,更好的是,确保你放在首位的操作数的类型是正确的。
由于双等号具有强制类型转换的行为,所以它会打破一般的传递性规则,这点有点吓人,请看下面的列子:
"" == 0 //true - 空字符串会被强制转换为数字0. 0 == "0" //true - 数字0会被强制转换成字符串"0" "" == "0" //false - 两操作数都是字符串所以不执行强制转换
如果使用三重等号,上面的三个比较都将返回false。
parseInt不把10作为数字基数
如果你忽略parseInt的第二个参数,那么数字的基数将由下面的规则所决定:
- 默认基数为10,即按10进制解析
- 如果数字以0x开头,那么基数为16,即按16进制解析
- 如果数字以0开头,那么基数为8,即按8进制解析
一个常见的错误是我们让用户输入以0开头的数字,这时候它就按8进制的方式去解析了,于是我们就看到了如下的效果:
parseInt("8"); //8 parseInt("08"); //0
因此,我们很多时候都会指定parseInt的第二个参数,如下所示:
parseInt("8", 10); //8 parseInt("08", 10); //8
ECMAScript5方面的说明:ECMAScript已不再支持8进制的解析假设,另外,如果忽略parseInt的第二个参数将会引起JSLint的警告。
字符串替换
字符串替换函数仅仅会替换第一个匹配项,并不能替换你所期望的全部匹配项。如下代码:
"bob".replace("b", "x"); // "xob" "bob".replace(/b/, "x"); // "xob" (使用了正则表达式)
如果要替换所有的匹配项,我们可以使用正则表达式,并为他它添加全局修饰符,如下代码:
"bob".replace(/b/g, "x"); // "xox" "bob".replace(new RegExp("b", "g"), "x"); // "xox" (alternate explicit RegExp)
全局修饰符确保了替换函数找到第一个匹配项后不会停止对下一个匹配项的替换。
“+"操作符会执行相加操作和字符串连接操作
php作为另一种弱类型语言,可以使用”.“操作符对字符串进行连接。Javascript却不是这样的 - 所以当操作数是字符串的时候”a+b“通常是执行连接操作。如果你想执行数字相加那你就要引起注意了,因为输入的内容可能是字符串类型的,所以你在执行相 加操作前需要先将其转换成数字类型,代码如下:
1 + document.getElementById("inputElem").value; // 连接操作 1 + Number(document.getElementById("inputElem").value); // 相加操作
需要注意的是,相减操作会尝试将操作数转换成数字类型,代码如下:
"3" - "1"; // 2
尽管有时候你想用减法将字符串从另一个字符串中减掉,但这时候往往会产生一些逻辑错误。
很多时候我们用数字和空串相加来实现数字转换成字符串的操作,代码如下:
3 + ""; // "3"
但是这样做并不好,所以我们可以用String(3)来取代上面的方法。
typeof
typeof这会返回一个javascript基本类型的实例的类型。Array实际上不是基本类型,所以typeof Array对象将返回Object,代码如下:
typeof {} === "object" //true typeof "" === "string" //true typeof [] === "array"; //false
当你对自己的对象的实例使用这个操作符时将会得到相同的结果(typeof = "object")。
另外说明一点,”typeof null“将返回”object“,这个有点诡异。
instanceof
instanceof返回指定对象是否是由某个类构造的实例,这个对我们检查指定对象是否是自定义类型之一很有帮助,但是,如果你是用文本语法创建的内置类型那可能会得出错误的结果,代码如下:
"hello" instanceof String; //false new String("hello") instanceof String; //true
由于Array实际上不是内置类型(只是伪装成内置类型 - 因此对它使用typeof不能得到预期的结果),但是使用instanceof就能得到预期效果了,代码如下所示:
["item1", "item2"] instanceof Array; //true new Array("item1", "item2") instanceof Array; //true
唉,不爽!总的来说,如果你想测试Boolean, String, Number, 或者Function的类型,你可以使用typeof,对于其他的任何类型,你可以使用instanceof测试。
哦,还有一点,在一个function中,有一个预定义变量叫“arguments”,它以一个array的形式传递给function。然而,它并不是真正的array,它只是一个类似array的对象,带有长度属性并且属性值从0-length。非常奇怪...你可以用下面的小伎俩将它转换成真正的数组:
var args = Array.prototype.slice.call(arguments, 0);
这个对由getElementsByTagName返回的NodeList对象也是一样的 - 它们都可以用以上的代码转换成合适的数组。
eval
eval 可以将字符串以javascript代码的形式来解析执行,但是一般来说我们不建议这么做。因为eval非常慢 - 当javascript被加载到浏览器中时,它会被编译成本地代码;然而执行的过程中每次遇到eval表达式,编译引擎都将重新启动执行编译,这样做的代价太大了。而且这样做也丑陋无比,有很多eval被滥用的例子。另外,在eval中的代码会在当前范围内执行,因此它可以修改局部变量,以及在你的范围内添加一些让你意想不到的东西。
JSON 转换是我们经常要做的;通常我们使用“var obj = eval(jsonText);”来进行转换。然而现在几乎所有的浏览器都支持本地JSON对象,你可以使用“var obj = JSON.parse(jsonText);”来替代前面的代码。相反你也可以用“JSON.stringify”将JSON对象转换成字符串。更妙的是,你可以使用“jQuery.parseJSON”来完成上述的工作。
setTimeout和setInterval函数的第一个参数可以用字符串作为函数体来解析执行,当然,我们也不建议这样做,我们可以用实际的函数来替代。
最后,Function的构造函数和eval非常像,唯一不同的是,Function构造函数是在全局范围内执行的。
with
with表达式将为你提供访问对象属性的速记方式,但我们是否应该使用它,仍然存在矛盾的观点。Douglas Crockford不太喜欢它。John Resig在他的书中有找了很多with
补充:web前端 , JavaScript ,
上一个:Jquery封装tab自动切换效果
下一个:js倒计时代码
- 更多JAVA疑问解答:
- java怎么在线读取ftp服务器上的文件内容
- 关于程序员的职业规划
- HTML和JSP矛盾吗?
- java小程序如何打包?
- java怎么split路径文件名?
- jsp+javaBean中Column 'ordersPrice' specified twice的错误
- Java TCP/IP Socket网络编程系列
- 大家来讨论一下我到底该用什么好?Swing 还是 JavaFX
- 关于Hibernate实体自身多对一的抓取问题
- 关于apache2+tomcat群集出现的问题
- spring 获取上下文问题
- SSH 导入导出excel 谁有这块的资料吗?
- Ext TreePanel 刷新问题
- springmvc 加载一个jsp页面执行多个方法 报404
- checkbox数组action怎么向页面传值