Array.sort()

数组的默认排序是 按照字典排序 的,即使用字符串比较(原因想想也知道)

所以就可能出现以下情况:

1
2
3
4
[9,80,3,10,5,6].sort()

// [ 10, 3, 5, 6, 80, 9 ]
// Oops!

教训:一定一定要在使用数组排序方法传入比较函数啊

1
2
3
4
5
[9,80,3,10,5,6].sort(function(a, b) {
  return a - b;
});

// [ 3, 5, 6, 9, 10, 80 ]

Date

Date的getXXX系列也是最让人混乱的一个地方:

getFullYear() -> 这才是常用的4位数字表示年份 getMonth() -> 返回值是0-11,表示1月到12月 getDate() -> 返回值是1-31,表示1日到31日(视月份而定) getDay() -> 返回值是一周的某一天不是一个月的某一天 getHours() -> 返回值是0-23 getMinutes() -> 返回值是0-59 getSeconds() -> 返回值是0-59

想让数字以双位数显示可以用下面的函数

1
2
3
function addZero(n) {
  return (n < 10 ? '0' : '') + n;
}

Add (operator +)

由于字符串拼接的存在,+号几乎把所有的东西优先转换成字符串类型。同时+号又作为加号存在,于是就出现了以下噩梦般的场景

减号、乘除号则是优先转换成数字

undefined转换为数字是NaN, null转换为数字是0

1
2
3
4
5
1 + '2'
// -> '12'

1 - '2'
// -> -1

parseInt

parseInt(string, radix);

ECMAScript3会把0X识别为8进制,于是在省略第二个参数radix的情况下,就会出现以下情况

1
2
3
4
5
6
7
8
parseInt('01'); //equals 1
parseInt('02'); //equals 2
parseInt('03'); //equals 3
parseInt('04'); //equals 4
parseInt('05'); //equals 5
parseInt('06'); //equals 6
parseInt('07'); //equals 7
parseInt('08'); //equals 0 !!

虽然ES5已经修复了这个问题,但是最好还是继续使用解决方案(或者避免使用parseInt)。

解决方案:

1
2
3
4
5
parseInt('08', 10); // 8
+'08';              // 8
~~'08';             // 8
new Number('08');   // 8
Math.ceil('08');    // 8

参考链接

this

以前提到过的 函数调用时,this会指向全局对象 问题:

在对象里调用函数(不是方法),this也会指向全局对象

使用ES6的=>已经不在有这个问题了

最简单的例子:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
var bob = {
  name: 'bob',
  friends: ['john', 'foo', 'bva'],
  printFriends: function() {
    this.friends.forEach(function(friendName) {
      console.log(this.name + ' knows ' + friendName);
    });
  }
};
bob.printFriends();

// output:
//
// undefined knows john
// undefined knows foo
// undefined knows bva

伪块级作用域

JavaScript使用的是函数作用域(Function Scope),但是它又用了类C语法的花括号,让很多人误以为是块级作用域(Block Scope),导致了很多理解上的问题

1
2
3
4
5
6
7
var x = 1;
console.log(x); // 1
if (true) {
  var x = 2;
  console.log(x); // 2
}
console.log(x); // 2

不过在ES6已经有let来实现块级作用域了