今天在网上瞎逛,无意间看到一个问题:一个数字乘以一个日期等于多少?
看得心里一惊,毫无防备地被这种鬼马精灵的问题戳中了盲点。于是赶紧研究一番。
3 * new Date() // 4692361990902
看来结果是3乘上了时间戳。
Date的时间戳怎么获取呢?我们知道是
new Date().valueOf() // 1564120663634
难道是乘上了valueOf()的值?
找到了valueOf函数是在Object的原型中定义的。
Object.prototype.valueOf // ƒ valueOf() { [native code] }
是不是说3乘上一个对象,都是乘上它的valueOf()的值呢?来试一下!
function Test(value) {
this.value = value;
}
Test.prototype.valueOf = function() {
return this.value;
}
const test = new Test(3);
3 * test; // 9
的确如此!
那我们再来看看默认的valueOf是什么。
function Test(value) {
this.value = value;
}
const test = new Test(3);
test.valueOf(); // Test {value: 3}
3 * test; // NaN
返回的是对象本身。这时候3乘上它就是NaN。
常见的内置对象的valueOf值:
Number(3).valueOf(); // 3
String("3").valueOf(); // "3"
[1,2,3].valueOf(); // [1, 2, 3]
Boolean(3).valueOf(); // true
(function(){}).valueOf(); // ƒ (){}
({a:3}).valueOf(); // {a: 3}
...
从上面结果可以粗略总结出,如果没有对valueOf进行定义的话,那么返回值即是对象本身。
再去看一下valueOf的文档。
链接
JavaScript calls the valueOf method to convert an object to a primitive value. You rarely need to invoke the valueOf method yourself; JavaScript automatically invokes it when encountering an object where a primitive value is expected.
valueOf是用来返回对象的原始值。难怪数字乘对象是乘以它的valueOf值。
那么数字与几个基本类型数据相乘会怎么样呢?
3 * null; // 0
3 * undefined; // NaN
3 * "s"; // NaN
3 * "3"; // 9
3 * true; // 3
3 * false; // 0
3 * 3; // 9
3 * NaN; // NaN
3 * {}; // NaN
3 * [3]; // 9
3 * Symbol(3); // Uncaught TypeError: Cannot convert a Symbol value to a number
原来是这样,数字与基本类型数据相乘时,其他数据又会进行类型转换。
再把相乘顺序调过来会怎样?
{} * 3; // Uncaught SyntaxError: Unexpected token *
其他结果相同,只有这个报了错。
({}) * 3; // NaN
{}是JavaScript的大括号,对不起,打扰了~~
总结一下。就是数字与对象相乘,会与对象的valueOf()相乘。基本类型之间相乘,会进行类型转换再相乘。