建议10:谨记对象非空特性
JavaScript从来没有真正的空对象,因为每个对象都可以从原型链中取得成员,这种机制会带来很多麻烦。例如,在编写统计一段文本中每个单词的出现次数的代码时可以这样设计:先使用toLowerCase方法统一转换文本为小写格式,接着使用split方法以一个正则表达式为参数生成一个单词数组,然后可以遍历该数组中每个单词,并统计每个单词出现的次数。
- var i, word;
- var text = "A number of W3C staff will be on hand to
- HTML5, CSS, and other technologies of the Open Web Platform.";
- var words = text.toLowerCase().split(/[s,.]+/);
- var count = {};
- for( i = 0; i < words.length; i += 1) {
- word = words[i];
- if(count[word]) {
- count[word] += 1;
- } else {
- count[word] = 1;
- }
- }
在执行结果中,count["on"]的值为1, count["of"]的值是3,而count.constructor却包含着一个看上去令人不可思议的字符串。在主流浏览器上,count.constructor将会返回字符串:function Object (){[native code]}。其原因是count对象继承自Object.prototype,而Object.prototype包含一个名为constructor的成员对象。count.constructor的值是一个Object。+=运算符,就像+运算符一样,如果它的运算数不是数字时会执行字符串连接的操作而不是加法运算。因为count对象是一个函数,所以+=运算符将其转换成一个莫名其妙的字符串,然后再把一个数字1加在它的后面。
采用与处理for in中问题相同的方法来避免类似的问题:用hasOwnProperty方法检测成员关系,或者查找特定的类型。在当前情形下,可以编写如下过滤条件:
- if (typeof count[word] === 'number') {
- }