6

Given that a literal number not strictly an instance of Number, why can I call prototype methods of Number (or String, or Boolean) objects on the corresponding literal objects? Is this standard behavior across browsers?

What exactly is happening when this occurs? I suspect it's coercing the literal into the corresponding type before calling the method, because when I inspect typeof this in the method, it's returning 'object' rather than 'number'.

user3840170
  • 26,597
  • 4
  • 30
  • 62
Triynko
  • 18,766
  • 21
  • 107
  • 173
  • 3 is not an instance of Number, it's a type `number`. For an instance of something, it would need to be of type `object`. So `typeof 3 = number`, `typeof new Number(3) = object`, You can coerce a built in type 'number, string' etc, by `Object(3) instanceof Number`, this would return true, you could also do for other built's like String etc. or either `var x = 3; x = Object(x);` x is now instanceof Number. – Keith Nov 08 '16 at 16:14
  • 2
    So if you wanted a simple isNumber check -> `function isNumber(n) { return typeof n === 'number' || n instanceof Number; }` – Keith Nov 08 '16 at 16:21
  • No, I already define those checks. In fact, that implementation isn't safe across browser windows for instances of Number that come from another window. It's better to use `function isNumber(n) { return Object.prototype.toString.call(n) === '[object Number]'; }`, which works for number primitives, number intances, and number instances from other windows. It's also the default implementation for shims like Array.isArray. – Triynko Nov 08 '16 at 16:24
  • `isn't safe across browser windows`, isn't that the case of `instanceof` that your talking about here?.. You mentioned nothing about IPC between windows / iframes. So I'm a little confused why your even talking about instanceof in this respect. – Keith Nov 08 '16 at 16:26
  • **See Also**: [Why is 4 not an instance of Number?](https://stackoverflow.com/q/472418/1366033) – KyleMit Oct 13 '21 at 01:55

1 Answers1

6

The literal is not coerced into an instance.

What happens internally, is that an instance is created, the value is copied to the instance and the method is carried out using the instance. Then the instance is destroyed. The literal is not actually being used to carry out the method. This "wrapper" object concept is also used with string primitives when they are used like String objects. This behavior is standard.

3 is a number literal. Not an instance of the Number type. JavaScript has a primitive number type and a native Number object.

From MDN: In contexts where a method is to be invoked on a primitive string or a property lookup occurs, JavaScript will automatically wrap the string primitive and call the method or perform the property lookup.

Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
  • That's not what I'm asking at all. That's the given. The question is why can I call methods of Number on a literal that is NOT a Number. – Triynko Nov 08 '16 at 15:58
  • 2
    @You keep editing your question and I keep updating my answer to keep up! – Scott Marcus Nov 08 '16 at 15:59
  • No, I only edited the first line to clarify. The question has always stated that 3 is not an instance of Number, and asks why I can still call methods of Number on it. Furthermore, it's asking whether it's standard/reliable behavior. This answers has addressed neither. First, it restated the given, then it restated my suspiction that it's coercing it into an instance. It still hasn't addressed whether it's standard behavior. – Triynko Nov 08 '16 at 16:00
  • @Triynko You can argue or look at my answer, which (in bold) answers your question. – Scott Marcus Nov 08 '16 at 16:01
  • It doesn't answer it, even after your 4th edit, lol. See previous comment. – Triynko Nov 08 '16 at 16:01
  • 1
    The edits have been purely grammatical. That complex boxing is an awfully big assertion to make without any references in the spec. The way you differentiate between the types is misleading. – ssube Nov 08 '16 at 16:02
  • "why can I call prototype methods of Number (or String, or Boolean) objects on the corresponding literal objects" and "What exactly is happening when this occurs?" The bold text answers both these questions. – Scott Marcus Nov 08 '16 at 16:03
  • I trust that the boxing is occurring, so that answers half of it. But is it standard/reliable behavior. I'm more concerned with whether my definition of, for example, Number.prototype.equals, will consistently and reliably be invoked on numeric literals on older browsers, or if this is something special or new. – Triynko Nov 08 '16 at 16:03
  • 2
    Yes it is standard behavior. – Scott Marcus Nov 08 '16 at 16:03
  • Thanks! I'll mark it as the answer once I verify where it is in the spec. – Triynko Nov 08 '16 at 16:05
  • 1
    Very relevant: http://www.jisaacks.com/javascript-boxing/ as well as https://javascriptweblog.wordpress.com/2010/09/27/the-secret-life-of-javascript-primitives/ – Triynko Nov 08 '16 at 16:07
  • Found it in the spec! See "ToObject": http://www.ecma-international.org/ecma-262/5.1/#sec-9.9 Very clear. – Triynko Nov 08 '16 at 16:10