Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatic javascript type coercion

Tags:

javascript

This has become more of a pondering about how javascript works, than an actual problem to fix. In the case of a statement like

var str = 9 + " some words here";

The resultant str var would contain the value "9 some words here". My question is what function does javascript use to automatically coerce the Number object '9' into a string to be concatenated with the String object " some words here", and is this function changeable/overrideable.

This started from me needing to output single digits with a preceding 0 on a page. This was easy enough to accomplish with a quick prototype function on the Number object

Number.prototype.SpecialFormat = function() {
  if(this < 10) {
    return "0" + this;
  }
  else {
   return this.toString();
  }
};

And call it with a simple (9).SpecialFormat() + " words here";

But that got me wondering if I could overwrite the toString function on a Number with a

Number.prototype.toString = function() {
  if(this < 10) {
    return "0" + this;
  }
  else {
   return this;
  }
};

, and just let javascripts automatic conversion handle it for me, so I could use a standard 9 + " words here"; to get the same result "09 words here". This did not just implicitly work, I had to end up adding .toString to the 9 (9).toString() + " words here" (which upon taking a further look, would have resulted in some infinite loops).

So is there a way to override the built in functionality of a javascript native type ?

*Note: I realize this is likely a 'worst idea ever'

like image 234
Robin Giltner Avatar asked Dec 19 '13 17:12

Robin Giltner


People also ask

Does JavaScript support automatic type coercion?

Does JavaScript support automatic type conversion? Yes. It's usually called type coercion, but conversion is perfectly accurate.

What are the types of coercion?

And still there are only three types of conversion: numeric, string and boolean. coerced to true , no matter if an object or an array is empty or not. Objects are converted to primitives via the internal [[ToPrimitive]] method, which is responsible for both numeric and string conversion.

What is automatic type conversion in JavaScript?

JavaScript is a "loosely typed" language, which means that whenever an operator or statement is expecting a particular data-type, JavaScript will automatically convert the data to that type.

What are the difference between type conversion and type coercion in JavaScript?

Type conversion is similar to type coercion because they both convert values from one data type to another with one key difference — type coercion is implicit whereas type conversion can be either implicit or explicit.


2 Answers

The addition operator coerces its arguments to strings in step 7:

  • If Type(lprim) is String or Type(rprim) is String, then
    • Return the String that is the result of concatenating ToString(lprim) followed by ToString(rprim)

The ToString operation has special rules for numbers, detailed under "ToString Applied to the Number Type".

It appears that the abstract operation ToString(number) does not ever use Number.prototype.toString. In fact, ti's the other way around: the default Number.prototype.toString function employs the abstract numeric ToString algorithm. Thus, it's not possible to override the default behavior for the stringification of numbers during type coercion in ECMAScript 5, because there's no way to alter the language-defined ToString operation.

ToString does use the target's toString method when coercing objects to strings, but not number primitive values.

like image 152
apsillers Avatar answered Sep 28 '22 03:09

apsillers


(not strictly an answer but I need some space)

Be very careful with type coercion, especially when combining primitive types with their object counterparts because:

var n = 9;
typeof n; // "number"
n instanceof Number; // false!!

n = new Number(9);
n instanceof Number; // true, oh thank God
typeof n; // "object" what!!

Also, toString on Number doesn't actually work:

Number.prototype.toString = function () { return "foo" + this; };
var n = new Number(9);
"" + n; // "9", not "foo9"

A way to avoid this mess is by having:

var ns = {
    number: {
        specialFormat: function () /* .. */ }
    }
}

ns.number.specialFormat(9); // "09"
like image 38
Halcyon Avatar answered Sep 28 '22 05:09

Halcyon