最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Why does JS call `toString` method when object is added to a number - Stack Overflow

programmeradmin0浏览0评论

I know that when JS tries to represent an object as primitive, it calls valueOf method on an object. But today I found out that it also calls toString() method in the same situation:

var o = {};
o.toString = function() {return 1};
1+ o; // 2

Why? If I add valueOf method then toString is not called.

I know that when JS tries to represent an object as primitive, it calls valueOf method on an object. But today I found out that it also calls toString() method in the same situation:

var o = {};
o.toString = function() {return 1};
1+ o; // 2

Why? If I add valueOf method then toString is not called.

Share Improve this question edited Jul 10, 2016 at 10:56 Max Koretskyi asked Jul 10, 2016 at 10:53 Max KoretskyiMax Koretskyi 105k67 gold badges353 silver badges515 bronze badges 0
Add a comment  | 

3 Answers 3

Reset to default 10

I suppose the explanation lies in 8.6.2.6 chapter of ECMA-262 specification:

8.6.2.6 [DefaultValue]

[...]

When the [[DefaultValue]] method of O is called with hint Number, the following steps are taken:

  1. Call the [[Get]] method of object O with argument "valueOf".

  2. If Result(1) is not an object, go to step 5.

  3. Call the [[Call]] method of Result(1), with O as the this value and an empty argument list.
  4. If Result(3) is a primitive value, return Result(3).

  5. Call the [[Get]] method of object O with argument "toString".

  6. If Result(5) is not an object, go to step 9.

  7. Call the [[Call]] method of Result(5), with O as the this value and an empty argument list.
  8. If Result(7) is a primitive value, return Result(7).
  9. Generate a runtime error. When the [[DefaultValue]] method of O is called with no hint, then it behaves as if the hint were Number, unless O is a Date object (see section 15.9), in which case it behaves as if the hint were String.

Since your object doesn't implement valueOf, toString is used.

it all depends on the Hint. when you use 1 + o it is a number Hint because of the + operand so it would definitely use valueOf before toString.

If the hint is String, then toString is used before valueOf. for example try ["o",o].join("=")

All together would be:

var o = {};
o.toString = function() {return 1};
o.valueOf= function(){return 2};
1 + o; // 1+2=3 ==> it takes valueOf value
["o",o].join("") //o1 ==> it takes toString value

TL;DR

When ToPrimitive is called with no hint it acts as if the hint was number. That defines methods to be called: first valueOf then toString. If you haven't defined your own valueOf it will call Object.prototype.valueOf that returns this.

BTW in modern browsers you can be more specific about it

const a = {
   [Symbol.toPrimitive]: function(hint) {
       console.log(hint);
       return {
          'default': 1,
          'number': 2,
          'string': 'three'
       }[hint]
   }
}

console.log(a + 1); //default, 2
console.log(+a + 1); //number, 3
console.log(`${a} + one`); //string, three + one

Long read:

  1. Addition
  2. ToPrimitive
发布评论

评论列表(0)

  1. 暂无评论