ECMAScript 操作符的与众不同之处在于,它们能够适用于很多值,例如字符串、数字值、布尔值,甚至对象。不过,在应用于对象时,相应的操作符通常都会调用对象的 valueOf() 和(或)toString() 方法,以便取得可以操作的值。
valueOf() 方法
JavaScript调用valueOf方法将对象转换为原始值。你很少需要自己调用valueOf方法;当遇到要预期的原始值的对象时,JavaScript会自动调用它。默认情况下,valueOf方法由Object后面的每个对象继承。 每个内置的核心对象都会覆盖此方法以返回适当的值。如果对象没有原始值,则valueOf将返回对象本身。
JavaScript的许多内置对象都重写了该函数,以实现更适合自身的功能需要。因此,不同类型对象的valueOf()方法的返回值和返回值类型均可能不同。
对象 | 返回值 |
---|---|
Array | 返回数组对象本身 |
Boolean | 返回布尔值1 |
Date | 返回时间的毫秒数(从 1970 年 1 月 1 日起计) |
Function | 返回函数本身 |
Number | 返回数字值 |
Object | 返回对象本身(默认) |
String | 返回字符串值 |
Math & Error | 没有 valueOf 方法 |
你可以在自己的代码中使用 valueOf 将内置对象转换为原始值。 创建自定义对象时,可以覆盖 Object.prototype.valueOf() 来调用自定义方法,而不是默认 Object 方法。
操作符
一元操作符(++/– 和 +/-)
递增和递减以及一元加和一元减(操作符置于数值前)的转换规则是一致的,但是注意一元加和一元减(操作符置于数值前)的运算对数值不产生任何影响,也就是说等于转换后的原始值的数值大小,而递增和递减需要对数值执行加减 1。接下来介绍它们的规则:
- 包含有效数字字符的字符串,变量值转数字值,再执行相关操作
- 不包含有效数字字符的字符串,变量值转 NaN,再执行相关操作
- 布尔值,变量值转 0 或 1,再执行相关操作
- 浮点数值,直接执行相关操作
用于对象时,先调用 valueOf() 方法取得对象的原始值,然后对取得的原始值再进行以上 4 步中的规则。如果取得的原始值结果为 NaN,就再调用 toString() 方法后再应用前述规则。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21var s1 = "2";
var s2 = "a";
var s3 = false;
var s4 = 1.1;
var s5 = {
valueOf: function() {
return -1;
}
};
s1++ // 3
s2++ // NaN
s3++ // 1
s4-- // 0.10000000000000009(由于浮点摄入错误导致)
s5-- // -2
+s1 // 2
+s2 // NaN
-s3 // -0
-s4 // -1.1
-s5 // 1
布尔操作符(!和 && 和 ||)
非
- 操作数是对象、非空字符串和任意非 0 数值(包括 Infinite),都返回false
操作数是空字符串、数值 0、null、undefined 和 NaN,都返回 true
1
2
3
4
5
6
7
8
9console.log(!{a:1}); // false
console.log(!"blue"); // false
console.log(!12345); // false
console.log(!""); // true
console.log(!0); // true
console.log(!null); // true
console.log(!undefined); // true
console.log(!false); // true
console.log(!NaN); // true
与
在有一个操作数不是布尔值的情况下,逻辑与操作就不一定返回布尔值;此时,它遵循以下规则:- 第一个操作数是对象,返回第二个操作数
- 第二个操作数是对象,则第一个操作数的求值结果为 true 的请款下才会返回该对象
- 两个操作数都是对象,返回第二个操作数
- 有一个操作数是 null,则返回 null
- 有一个操作数是 NaN,则返回 NaN
- 有一个操作数是 undefined,则返回 undefined
或
在有一个操作数不是布尔值的情况下,逻辑或操作就不一定返回布尔值;此时,它遵循以下规则:
- 第一个操作数是对象,返回第一个操作数
- 第一个操作数求值的结果为 false,则返回第二个操作数
- 两个操作数都是对象,返回第一个操作数
- 两个操作数都是 null,则返回 null
- 两个操作数都是 NaN,则返回 NaN
- 两个操作数都是 undefined,则返回 undefined
加性操作符(+ 和 -)
如果两个操作符都是数值,执行常规的加减法计算,遵循如下规则:
- 有一个操作数是 NaN,相加和相减结果都为 NaN
- 两数都为 Infinite,相加结果为 Infinite,相减结果为 NaN
- 两数都为 -Infinite,相加结果为 -Infinite,相减结果为 NaN
两数分别为 Infinite 和 -Infinite:
- 相加:结果为 NaN
相减:
- Infinite 减 -Infinite,结果为 Infinite
- -Infinite 减 Infinite,结果为 -Infinite
- 两数都为 +0,相加和相减结果都为 +0
- 两数都为 -0,相加结果为 +0,相减结果为 -0
- 左右两数分别为 +0 和 -0,相加结果为 +0,相减结果为 -0
关系操作符(==/!= 和 ===/!==)
相等和不相等
- 有一个操作数是布尔值,先转换其为数值(0 或 1)再比较
- 有一个操作数是字符串,另一个是数值,先转换字符串为数值再比较
- 有一个操作数是对象,另一个操作数不是,则调用对象的 valueOf() 方法,用得到的基本类型值按照前面的规则继续比较
- null == undefined
- null 和 undefined 在比较之前不做任何转换
- 有一个操作数是 NaN,相等比较返回 false,不等比较返回 true
- 两个操作数都是 NaN,相等比较返回 false(因为按照规则,NaN != NaN)
如果两个操作数都是对象,则比较它们是不是同一个对象(如果两个操作数都指向同一个对象,则相等比较返回 true;否则,返回 false)
1
2
3
4
5
6
7
8
9console.log("NaN" == NaN); // false
console.log(5 == NaN); // false
console.log(NaN == NaN); // false
console.log(NaN != NaN); // true
console.log(null == undefined); // false
console.log(null == 0); // false
console.log(undefined == ""); // false
console.log(false == null); // false
console.log(false == undefined); // false
全等和不全等
全等和不全等只在两个操作数未经转换就相等的情况下返回 true,在这里一定记住:null !== undefined。