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