Arithmetic operators on JavaScript objects (with and without valueOf)

what happens when we "do math" to an object?

2025-02-19 17:12

On the JavaScript telegram (not my channel, but at the time of writing, it has almost 30,000 subscribers), there was a "challenge" quiz post that puzzled about 60% of quiz takers (including myself, of course!)

They posted this snippet:

let person = {
  name: 'Alice',
  age: 30,
  valueOf: function() {
    return this.age;
  }
};

let result = person + 10;
console.log(result);

They asked "What is the output?" with a multiple choice:

  • [object Object]10
  • undefined
  • 30
  • 40

All of them seemed like feasible responses, although 30 seemed the least likely. I guessed the first weird one. As stated earlier, I was incorrect. The correct answer was actually 40.

"What I actually first thought!"

So, it seemed to me that when we add a number to an object type, JavaScript looks through the object's properties and performs the arithmetic operator on a property that matches the data type. In this case, it was age, which was 30. Add 10 to that and we have, of course, a result of 40.

I actually was quite wrong but continued to experiment to learn more...

"So what is the person in the result?"

So I thought of playing around further and decided to add another property with a number type value:

let person = {
  name: 'Alice',
  age: 30,
  salary: 50000,
  valueOf: function() {
    return this.age;
  }
};

let result = person + 10000;
console.log(result);

In that case, we would actually get 10030 as the result. The person object seemed to be casted into the number of the person object's first property. It seemed to ignore any other property, even if it has a number data type.

I looked further to increase my understanding...

"So is person just the first numeric property?"

So, I tried string concatenation:

let person = {
  name: 'Alice',
  age: 30,
  valueOf: function() {
    return this.age;
  }
};

let result = person + ' Springs';
console.log(result);

I thought I would get Alice Springs. I got 30 Springs but I realized that I didn't even see the person's valueOf method property!!!

Looking it up, the valueOf method has this "built-in" characteristic that returns whatever primitive value we tell it to return. (In the case above, that was the age!)

"No, it's the valueOf, stupid!"

So, I tried changing the return to this.name:

let person = {
  name: 'Alice',
  age: 30,
  valueOf: function() {
    return this.name;
  }
};

let result = person + ' Springs';
console.log(result);

...to yield a result of Alice Springs !

So, this means that the valueOf property is a method with a special property name that will cast its parent object's variable into any primitive value (string, number, boolean, undefined, null, bigint, symbol), via its return statement!

Now, I fully understood it. Just simply knowing the answer !== understanding!

"So, if we don't use valueOf?"

Now, if we do not use valueOf, we will get a different result:

let person = {
  name: 'Alice',
  age: 30,  
};

let result = person + 10;
console.log(result);

The person variable simply gets stringified into [Object object].

So, a simple string concatenation occurs: the result will yield "[Object object]10"!

Summary

  • valueOf as a special object property name that allows us to write a method that returns a primitive value (such as another property within the same object, or some kind of concatenation of primitive values)
  • without valueOf we would simply get "[Object object]" every time we console.log an object variable