We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ValueOf是JavaScript中Object原型上少数几个方法之一,应该不能算是很偏门的函数,但是只有《JavaScript权威指南》上面有只言片语的描述,而对ES2015中相应的Symbol.toPrimitive更是鲜有提及。
Symbol.toPrimitive
首先,给出一个结论,valueOf和toString几乎都是在出现操作符(+-*/==><)时被调用, 并且valueOf几乎没有什么用。
valueOf
toString
那么,valueOf的作用是什么呢?按照语言标准上的说法就是,用于toPrimitive需要Number时,而toPrimitive出现的时机,说得简单一点就是,当需要一个Number或者String,但是被传入了一个对象时,就会执行这个操作。有一个常见的用法实际上是使用了valueOf:
toPrimitive
将Date对象转换为时间戳时,会很自然的用+ new Date(), 实际上是悄悄地调用了new Date().valueOf()
+ new Date()
new Date().valueOf()
详细地说,有如下场景,会出现偏好结果是Number的toPrimitive,也就是说valueOf可能被调用(如果没有valueOf的话,可以被toString等替代):
具体而言,当obj前后操作符是加法,以及减法、乘法、除法,以及调用Number(obj)以及new Number(obj)时。值得注意的是,parseInt, parseFloat等方法实际上不会调用ToNumber, 他们调用的是偏好String的toPrimitive。举个代码的例子:
Number(obj)
new Number(obj)
parseInt, parseFloat
ToNumber
class Test { valueOf() { return 1; } toString() { return '2'; } } const a = new Test(); console.log(parseInt(a, 10)); // 打印出2,也就是toString被调用了 console.log(Number(a));// 打印出1,也就是valueOf被调用了 const obj = {}; obj[a] = 1; console.log(obj); // 打印出 {‘2’: 1},也就是toString被调用了 const b = 0; const c = '0'; console.log(a + b); // 打印出 1, 也就是valueOf被调用了 console.log(a + c);// 打印出 10, 也就是还是ValueOf被调用
直接上代码:
class Test { constructor(val) { this.__val = val; } valueOf() { return this.__val; } } const a = new Test('12'); const b = new Test(2); console.log(a < b); // 打印出false,说明valueOf被调用,且两者不都是string时,转换为Number // 且如果不能转为Number,则值为NaN
嗯,我们可以得出如下结论,在应该使用“值”,也就是数值的地方,如果出现了对象,就会调用valueOf。
再给出一个例子,证明valueOf不存在时,可以用toString作为替代品
class Test { toString() { return '2'; } } const a = new Test(); console.log(parseInt(a, 10)); // 打印出2,也就是toString被调用了 console.log(Number(a));// 打印出2,也就是toString被调用了 const obj = {}; obj[a] = 1; console.log(obj); // 打印出 {‘2’: 1},也就是toString被调用了 const b = 0; const c = '0'; console.log(a + b); // 打印出 1, 也就是toString被调用了 console.log(a + c);// 打印出 10, 也就是还是toString被调用
但是反过来是不成立的,有的地方必须使用toString, 比如说把对象作为对象的key使用时,以及向parseInt中传入对象时。
parseInt
到这里,可以得出一个结论,一个对象想要在希望转化为数字的地方,通过给出特殊的valueOf来给出不同于期望转化为字符串的地方的值,最好的例子就是Date对象。
Date
另外,我们频繁提到的toPrimitive这个操作,在ES2015标准中,已经真的添加了这个方法,并且这个方法会比toString和valueOf的优先级都高,并且嘛,几乎都可以替代这俩货了, 给个例子:
class Test { valueOf() { return 1; } toString() { return '2'; } [Symbol.toPrimitive](hint) { console.log(hint); return 3; } } let a = new Test(); const obj = {}; obj[a] = 1; console.log(obj); // => string { '3': 1 } const b = 0; const c= '0'; console.log(a + b); // => default 3, default相当于number console.log(a + c); // => default 30 console.log(parseInt(a, 10)); // => string 3 console.log(Number(a)); // => number 3
上述代码中Symbol.toPrimitive方法可以接收参数,表示期望的类型,就像我们提到的,如果是string,就是期望获得字符串(也就是之前说的调用toString),如果是default或者number则希望获取一个数字(也就是之前说的优先调用valueOf,否则调用toString)。
可以看出,Symbol.toPrimitive是完完全全可以取代掉valueOf,甚至toString。
另外,++运算符也可以触发偏好Number的toPrimitive,而且很有意思的是toPrimitive系是内建函数,可以返回左值,所以可以用到对象上:
class Test { constructor(val) { this.__val = val; } [Symbol.toPrimitive](hint) { return this.__val; } } let a = new Test(1); console.log(++a); // => 2 let b = new Test('2'); b++; console.log(b); // => 3 let c = '1'; console.log(typeof c) // => 'string' console.log(++c) console.log(typeof c) // => 'numer', ++ 确实有转型的作用
The text was updated successfully, but these errors were encountered:
No branches or pull requests
首先,给出一个结论,
valueOf
和toString
几乎都是在出现操作符(+-*/==><)时被调用, 并且valueOf
几乎没有什么用。那么,
valueOf
的作用是什么呢?按照语言标准上的说法就是,用于toPrimitive
需要Number时,而toPrimitive
出现的时机,说得简单一点就是,当需要一个Number或者String,但是被传入了一个对象时,就会执行这个操作。有一个常见的用法实际上是使用了valueOf
:详细地说,有如下场景,会出现偏好结果是Number的
toPrimitive
,也就是说valueOf
可能被调用(如果没有valueOf
的话,可以被toString
等替代):具体而言,当obj前后操作符是加法,以及减法、乘法、除法,以及调用
Number(obj)
以及new Number(obj)
时。值得注意的是,parseInt, parseFloat
等方法实际上不会调用ToNumber
, 他们调用的是偏好String的toPrimitive
。举个代码的例子:直接上代码:
嗯,我们可以得出如下结论,在应该使用“值”,也就是数值的地方,如果出现了对象,就会调用valueOf。
再给出一个例子,证明
valueOf
不存在时,可以用toString
作为替代品但是反过来是不成立的,有的地方必须使用
toString
, 比如说把对象作为对象的key使用时,以及向parseInt
中传入对象时。到这里,可以得出一个结论,一个对象想要在希望转化为数字的地方,通过给出特殊的
valueOf
来给出不同于期望转化为字符串的地方的值,最好的例子就是Date
对象。另外,我们频繁提到的
toPrimitive
这个操作,在ES2015标准中,已经真的添加了这个方法,并且这个方法会比toString
和valueOf
的优先级都高,并且嘛,几乎都可以替代这俩货了, 给个例子:上述代码中
Symbol.toPrimitive
方法可以接收参数,表示期望的类型,就像我们提到的,如果是string,就是期望获得字符串(也就是之前说的调用toString),如果是default或者number则希望获取一个数字(也就是之前说的优先调用valueOf,否则调用toString)。可以看出,
Symbol.toPrimitive
是完完全全可以取代掉valueOf
,甚至toString
。另外,++运算符也可以触发偏好Number的
toPrimitive
,而且很有意思的是toPrimitive
系是内建函数,可以返回左值,所以可以用到对象上:The text was updated successfully, but these errors were encountered: