/ 昌里大金猪的空间 / 也谈谈Javascript中的几个"怪异"特性

也谈谈Javascript中的几个"怪异"特性

2011-06-11 posted in [javascript]

Andy CroxallTen Oddities And Secrets About JavaScript罗列了他认为的10个javascript怪异特性。纵观全文,其实有些特性也并不那么“怪异”。对于原文我不作翻译,就顺着文章谈一下自己的理解吧,希望对读者有所帮助。


1. Null is an Object(Null是一个Object)

1 alert(typeof null); //'object'

undefined代表无值的基本类型,null代表无值的引用类型。基本数据类型(number string boolean等等)是引用数据类型的子类(undefined是null的子类)。建议深入阅读理解Javascript_02_理解undefined和null

1 alert(null instanceof Object); //false

instanceof检测对象a是不是对象b的实例的原理是:检测对象b的prototype指向的对象是否在对象a的[[prototype]]链上,若在则返回true。由于null无值,不属于任何对象,故返回false,具体可参考Javascript Object Layout关系图。


2. NaN is a Number(NaN是一个Number)

1 alert(typeof NaN); //'Number'
2 alert(NaN === NaN); //false

根据MDC:The value of Number.NaN is Not-A-Number, same as the value of global object's NaN property. 也就是说NaN是Number的一个属性,也是全局对象中的一个属性,Number.NaN与NaN是一样的。NaN与任何一个数字不相等,并且与NaN本身也不相等。


3. An Array With No Keys == False (空数组等于false)

1 alert(new Array() == false); //true

new Array()的返回值为[],原表达式相当于[]==false,这个值为true,具体演变过程见圆心
类型转换的小乐趣。如果能够理解其中转化的奥妙,以下几段代码的执行结果也都不难解释。

1 var someVar = 0;
2 alert(someVar == false); //true

1 var someVar = []; //空数组
2 alert(someVar == false); //true
3 if (someVar) alert('hello'); //alert会执行, someVar会被计算为true值

1 var someVar = 0;
2 alert(someVar == false); //true
3 alert(someVar === false); //false

顺便说一句,Array长度的最大值为4,294,967,295即2^32-1The maximum length allowed for an array is 4,294,967,295.)
关于类型转化,推荐扩展阅读:Twisted logic: understanding truthy & falsy


4. replace() Can Accept a Callback Function(replace函数可接受一个回调函数)

一般我们会这么使用replace函数:
1 alert('10 13 21 48 52'.replace(/\d+/g, '*')); //用*来replace所有的数字
实际上,正如标题所言,replace后面接受一个Callback来进行一些额外的操作:

1 alert('10 13 21 48 52'.replace(/\d+/g, function(match) {
2     return parseInt(match) < 30 ? '*' : match;
3 }))//* * * 48 52

对于每个匹配的数字进行一次三元表达式的操作。


5. Regular Expressions: More Than Just Match and Replace(关于正则表达式,不仅仅只有match和replace函数)

除了match和replace函数以外,还可以使用test函数,调用方式如下:

1 alert(/\w{3,}/.test('Hello')); //alerts 'true'

以及RegExp对象,具体用法见文档。

关于正则的学习资料我推荐精通正则表达式。如果不是作科研,熟读前半本就行了。正则表达式30分钟入门教程也不错,常备案头温故知新。

  
6. You Can Fake Scope(作用域是可以改变的)

1 var animal = 'dog';
2 function getAnimal(adjective) { alert(adjective+' '+this.animal); };
3 var myObj = {animal: 'camel'};
4 getAnimal.call(myObj, 'lovely'); //'lovely camel'

相信任何一本Javascript书籍中都会提到callapply函数,推荐阅读这篇文章Function.apply and Function.call in JavaScript


7. Functions Can Execute Themselves(函数自己能够执行自己)

1 var someVar = 'hello';
2 setTimeout(function() { alert(someVar); }, 1000);
3 var someVar = 'goodbye';

代码执行结果为goodbye。setTimeout中的function是个函数申明,在1000ms后才会真正执行下去,此时变量someVar值是goodbye。对比一下下面这段代码:

1 var someVar = 'hello';
2 setTimeout((function(someVar) {
3     return function()  { alert(someVar); }
4 })(someVar), 1000);
5 var someVar = 'goodbye';

与第一段代码不同之处在于setTimeout中的function在声明完毕后会立即执行,之后someVar无论怎么变化都不会影响当前函数。


8. Firefox Reads and Returns Colors in RGB, Not Hex(Firefox会以RGB的形式返回颜色值,而不是16进制数)

01 <!--
02 #somePara { color: #f90; }
03 -->
08 var ie = navigator.appVersion.indexOf('MSIE') != -1;
09 var p = document.getElementById('somePara');
10 alert(ie ? p.currentStyle.color : getComputedStyle(p, null).color);

这段代码在大多数浏览器下会返回#f90,Firefox返回的却是rgb(255, 153, 0)。有意思的是,如果该节点的color有透明度,firefox能够以rgba的形式返回,这是hex值做不到的。为了屏蔽各种浏览器之间的差异情况,目前很多类库都有相应的取节点样式函数。


9. 0.1 + 0.2 !== 0.3

0.1+0.2实际输出值为0.30000000000000004,对此结果我还没有找到理论依据,猜测可能与Javascript的类型转换有关。文中作者给出了一个drawback,在一些对精度要求不是很严格的场合下使用

1 alert(num1 + num2 > shouldEqual - 0.001 && num1 + num2 < shouldEqual + 0.001); //true


10. Undefined Can Be Defined(undefined不能被defined)

1 undefined = "I'm not undefined!";
2 var someVar;
3 alert(someVar == undefined); //在firefox4下执行结果为true,其他浏览器为false

作者给出的这第10个特性是错误的,至少不完全正确。我在本地测试了一下,chrome11以及其他浏览器中undefined能够被defined,但firefox4下却不能。除了上述代码,还可以这么判断值是否undefined:
(x === void 0)
(typeof x == "undefined")//能够正常执行,即使x未声明



全文结束。