简体   繁体   中英

Does Number() explicitly call toString() when value is neither number nor string type? (e.g. function)

As the documentation describes this behaviour for parseInt(), but not for the Number() constructor called as a function, I was looking for some insight on whether this is reliable and if there's a reference to this from an official source. Sample code:

 let adder = (function () { let sum = 0 return function add(num) { sum += num add.toString = () => sum //method is overwritten to return value return add } })() console.log(Number(adder(5)(2)(3))) // => 10

See the specification . Calling Number will call ToNumeric(value) with the argument, which will call ToPrimitive with the argument, which will (usually) call OrdinaryToPrimitive with the argument and a hint of number , which does:

  1. Assert: Type(O) is Object.
  2. Assert: hint is either string or number.
  3. If hint is string, then
    1. Let methodNames be « "toString", "valueOf" ».
  4. Else,
    1. Let methodNames be « "valueOf", "toString" ».
  5. For each element name of methodNames, do
    1. Let method be ? Get(O, name).
    2. If IsCallable(method) is true, then
      1. Let result be ? Call(method, O).
      2. If Type(result) is not Object, return result.
  6. Throw a TypeError exception.

So, in the case of converting an object to a numeric primitive, will first attempt to call a valueOf method on the object, if it exists. If such a method doesn't exist, it'll attempt to call the toString method on the object.

Yes, relying on toString being invoked in case valueOf doesn't exist is reliable.

Live snippet illustrating how valueOf is called first, if it exists:

 let adder = (function () { let sum = 0 return function add(num) { sum += num add.toString = () => { console.log('toString called'); return sum; //method is overwritten to return value }; add.valueOf = () => { console.log('valueOf called'); return sum; //method is overwritten to return value }; return add } })() console.log(Number(adder(5)(2)(3))) // => 10

If the object doesn't have an own property of toString or valueOf , Object.prototype.toString will be called, resulting in [object Object] - but that won't be coercable to a number, resulting in NaN .

 let adder = (function () { let sum = 0 return function add(num) { sum += num return add } })() console.log(Number(adder(5)(2)(3))) // => 10

And if the object doesn't inherit from Object.prototype and doesn't have toString or valueOf anywhere in its prototype chain, an error will be thrown:

 let adder = Object.create(null); console.log(Number(adder))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM