Skip to content

Instantly share code, notes, and snippets.

@dtipson
Last active October 20, 2020 09:37
Show Gist options
  • Save dtipson/7debac370d2aded7fd1055d0e252a946 to your computer and use it in GitHub Desktop.
Save dtipson/7debac370d2aded7fd1055d0e252a946 to your computer and use it in GitHub Desktop.
var object = {
value:5,
increment(){ return ++this.value; }
};
/*
But of course, even though that value is central to what the object is,
it's not really a _primitive_ value in the sense that we can directly coerce it into a number or string:
*/
Number(object); //-> NaN
`${object}`; //-> [object Object]
//but now we define some custom behavior for coercion on complex objects. Let's look at this object I've already created
//->object2
//Like the first object, it's a real object with both a value key and an increment key that defines a method on it
//Object.keys(object2);//-> ["value", "increment"]
//JSON.stringify(object2);//"{"value":5}"
//But now when we coerce it to a primitive value...
//Number(object2); //-> 5
//`${object2}`; //-> "5"
//Here's what's actually going on under the hood:
var object2 = {
value:5,
increment(){ return ++this.value; },
[Symbol.toPrimitive](hint){
if (hint === "number") {
return this.value;
}
if (hint === "string") {
return String(this.value);
}
return true;
}
};
/*
So, defining Symbol.toPrimitive allows you to alter what happens when a complex value is coerced into a string or a number.
You can do the same thing for arrays. Here I have an array of prices, and I can make it such that coercing it into a string
or a number will automatically sum its contents and return them instead of doing something weird:
*/
var cartPrices = [10,20,30];
var sum = Symbol('sum');
var summable = {
[sum]: function(){ return this.reduce((acc,item)=>acc+item,0); },
[Symbol.toPrimitive]: function(hint){
if(hint==="number"){
return this[sum]();
}
if(hint==="string"){
return String(this[sum]());
}
return true;
}
};
//extending cartPrices with new behavior
Object.assign(cartPrices, summable);//-> [10, 20, 30]
console.log(
"total: $"+String(cartPrices), //-> "total: $60"
`total: $${cartPrices}`, //-> "total: $60"
Number(cartPrices) //-> 60
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment