7

If we add a method to Number function (or Boolean or String) like this

Number.prototype.sayMyNumber = function(){
    return "My number is " + this;
}

and then create a number object assign it to a variable

var num1 = new Number(34); 
num1.sayMyNumber(); // it says "My number is 34"

This is fine and expected as we created 'Number' object.

Similarly, if I create a primitive variable

num2 = 34;
num2.sayMyNumber(); // it says "My number is 34"

Surprisingly, num2 also has a method sayMyNumber() even though we did not create a Number object explicitly.

Then I tried it like this,

34.sayMyNumber(); // error, this does not work 

Why does num2 work?

Update

This is a follow up question that I asked in the comment section, I am putting it here for better visibility

Below answers mention that num2 is considered as a 'Number' object internally. This further confuses me.

typeof num1 === "number" // returns false
typeof num2 === "number" // returns true

typeof num1 === "object" // returns true
typeof num2 === "object" // returns false

Does this not mean that num2 is not an "object" ? If it is not an "object" then how can it be an instance of 'Number' ?

Flying Gambit
  • 1,238
  • 1
  • 15
  • 32
  • 2
    In `34.sayMyNumber()` dot is treated as **decimal point** which lead to error. You have to use parens if you want to force method invocation in this case. `num2` works cause any number in JS is `Number` instance even if it is defined as literal – hindmost Feb 28 '16 at 08:37
  • It does not work even when I put it like this `(2).sayMyNumber()`. Not sure if this is the same as above – Flying Gambit Feb 28 '16 at 08:38
  • honestly (whatever_number).yourFunction() works – oiledCode Feb 28 '16 at 08:40
  • I just now double checked `(2).sayMyNumber()` does work – Flying Gambit Feb 28 '16 at 08:44
  • 1
    So far the answers say that num2 is also treated as an Number object, then why do they have different values for typeof – Flying Gambit Feb 28 '16 at 08:58
  • 1
    `34 .sayMyNumber()` :-) – swenedo Feb 28 '16 at 10:13
  • A similar thing happens in Java called autoboxing. Whereby if you try to interact with a primitive type, the compiler will automatically wrap it in its associated wrapper class. – Phil Mander Feb 28 '16 at 10:21
  • @Bergi The answers to the question http://stackoverflow.com/questions/5751704/javascript-do-primitive-strings-have-methods does not say why typeof gives a different value – Flying Gambit Feb 28 '16 at 10:45
  • @FlyingGambit: That's the problem with asking 3 different questions in one post :-) You might find further answers [here](http://stackoverflow.com/a/15704855/1048572) or [there](http://stackoverflow.com/q/33696067/1048572). Indeed, `num2` is not an object. It only gets implicitly converted to one when a property lookup is done on it. – Bergi Feb 28 '16 at 13:58

3 Answers3

4

The primitive type Number has a corresponding object representation, which you can create with new Number. This is an object and is therefore of a different data type than the primitive type Number.

If you call Number(34) (without new) an object isn't created, but the Number function performs a type conversion, to a primitive number value.

var num1 = new Number(34); // object
var num2 = 34; // primitive

When you call sayMyNumber() on the primitive number num2, JavaScript internally converts the primitive temporarily to its equivalent object version. And because you added sayMyNumber() to Number.prototype you have access to the function.

The reason 34.sayMyNumber() doesn't work is because when JavaScript engine parses your source code, it has to interpret just what a dot means in a given context. In the case of 34.sayMyNumber() the dot is potentially ambiguous. Does it mean the decimal separator? Or does it mean object member access? JavaScript opts to interpret all integers followed by a dot as representing part of a floating point number. But as there is no such number 34.sayMyNumber(), it raises a SyntaxError. Read more here

swenedo
  • 3,074
  • 8
  • 30
  • 49
  • How can they be same when typeof is different `typeof num1 = "object"` and `typeof num2 = "number"` – Flying Gambit Feb 28 '16 at 08:50
  • Didn't you mean `var num1 = Number(34)`. A `Number` is not an object so `new` does not make sense. – doug65536 Feb 28 '16 at 09:01
  • You are right @doug65536. I just copied OP's code line and didn't think of `new`. – swenedo Feb 28 '16 at 09:07
  • @doug65536 Number is a native function with dual behaviour `typeof (Number(34)) is "number"` and `typeof (new Number(34)) is "object"`. We wanted to make comparison between primitive and object, hence the use of new – Flying Gambit Feb 28 '16 at 09:08
  • _34.sayMyNumber(); is a syntax error. A variable cant start with a number._ Wrong explanation. There is **no variable**, that is an **expression** which obviously _may start with a number_. The real cause is different (wrong meaning of dot symbol) – hindmost Feb 28 '16 at 09:37
  • Thanks @hindmost, have fixed it. – swenedo Feb 28 '16 at 09:48
  • 2
    Also frankly I don't understand how exactly that quote from MDN (about loosely typed language) can lead to conclusion that definitions by number literal and `Number` constructor are the same. – hindmost Feb 28 '16 at 10:23
  • `34` or `Number(34)` is not a Number instance - it's not an object. I can't inherit from `Number.prototype`. – Bergi Feb 28 '16 at 10:33
  • @Bergi can you explain why? [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/prototype) says **All Number instances inherit from Number.prototype** – swenedo Feb 28 '16 at 11:27
  • @swenedo, how does 34.blahblah treated as decimal? It suppose to be a syntax or illegal statement. – Sathik Khan Feb 28 '16 at 11:42
  • @SathikKhan When a JavaScript engine parses your source code, it has to interpret just what a dot means in a given context. In the case of `34.sayMyNumber()` the dot is potentially ambiguous. Does it mean the decimal separator? Or does it mean object member access? JavaScript opts to interpret all integers followed by a dot as representing part of a floating point number. But as there is no such number `34.sayMyNumber()`, it raises a SyntaxError. [Read more here](http://adripofjavascript.com/blog/drips/numbers-and-javascripts-dot-notation.html) – swenedo Feb 28 '16 at 11:48
  • @swenedo: As I said, `34` or `Number(34)` are no Number *instances* (objects), they're primitive *numbers*. – Bergi Feb 28 '16 at 13:50
  • @Bergi Yes but `34` and `Number(34)` get converted to a Number instance when `.sayMyNumber()` is called, and they get access to the the the function OP added to `Number.prototype`... Hmm.. I should probably read up on this again, I'm a little bit confused now :) – swenedo Feb 28 '16 at 14:37
  • Yes, this implicit conversion is important, you should focus your answer on it. – Bergi Feb 28 '16 at 14:48
  • I've updated the answer. I have done some reading, and think it is correct now :) – swenedo Feb 29 '16 at 13:24
  • how do you explain num2.toString()? – SuperUberDuper Feb 09 '17 at 10:28
-2

JavaScript coerces between primitives and objects. In this case the number value is coerced to a Number object in order to access the prototype method sayMyNumber. Actually, in this way primitives have access to all the properties and methods defined by their respective object constructors. However, they are different from the objects as they are immutable.

Thus, (34).sayMyNumber(); works; so does (34).toFixed() or (34).toPrecision().

As for 34.sayMyNumber();, as hindmost pointed out, is a syntax error.

jaibatrik
  • 6,770
  • 9
  • 33
  • 62
-4

For both,

var num1 = new Number(34); 
num2 = 34;

You are assigning "Number" type values to both num1 and num2 variables. So it calls the prototype, which attached to the "Number".

But calling 34.sayMyNumber has syntax error and its an illegal statement.

If anyone has question on this please refer... https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number

Sathik Khan
  • 439
  • 4
  • 13
  • Can someone explain why downvotes? I will fix if something wrong here... – Sathik Khan Feb 28 '16 at 10:58
  • 1
    `num1` and `num2` do have different types. – Bergi Feb 28 '16 at 13:51
  • I have mentioned type values... And mozillaa says "The numeric value of the object being created... " new Number(value); If the argument cannot be converted into a number, it returns NaN. In a non-constructor context (i.e., without the new operator), Number can be used to perform a type conversion... https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number... – Sathik Khan Feb 28 '16 at 17:40