JavaScript allows us to work with primitives (strings, numbers, etc.) as if they were objects. Let’s look at the key distinctions between primitives and objects.
A primitive
An object
{}
, for instance: {name: "John", age: 30}
. There are other kinds of objects in JavaScript; functions, for example, are objects.One of the best things about objects is that we can store a function as one of its properties.
let john = { name: "John", sayHi: function() { alert("Hi buddy!"); } }; john.sayHi(); // Hi buddy!
Like this many built-in objects already exist, such as those that work with dates, errors, HTML elements, etc. They have different properties and methods. But, these features come with a cost! Objects are “heavier” than primitives. They require additional resources to support the internal machinery. But as properties and methods are very useful in programming, JavaScript engines try to optimize them to reduce the additional burden.
There are many things one would want to do with a primitive like a string or a number. It would be great to access them as methods. But if you want to make primitive type behaves like an object you also need to make them as fast as possible. The solution looks a little bit awkward, but here it is:
The “object wrappers” are different for each primitive type and are called: String
, Number
, Boolean
and Symbol
. Thus, they provide different sets of methods.
For instance, there exists a method str.toUpperCase()
that returns a capitalized string.
let str = "Hello"; alert( str.toUpperCase() ); // HELLO
Here’s what actually happens in str.toUpperCase()
:
str
is a primitive. So in the moment of accessing its property, a special object is created that knows the value of the string, and has useful methods, like toUpperCase()
.str
alone.So primitives can provide methods, but they still remain lightweight.
The special primitives null and undefined are exceptions. They have no corresponding “wrapper objects” and provide no methods. In a sense, they are “the most primitive”. An attempt to access a property of such value would give the error:
alert(null.test); // error
Some languages like Java allow us to create “wrapper objects” for primitives explicitly using a syntax like new Number(1)
or new Boolean(false)
. In JavaScript, that’s also possible for historical reasons, but highly unrecommended. Things will go crazy in several places. For instance -
alert( typeof 1 ); // "number" alert( typeof new Number(1) ); // "object"!
And because what follows, zero, is an object, the alert will show up:
let zero = new Number(0); if (zero) { // zero is true, because it's an object alert( "zero is truthy?!?" ); }
All numbers in JavaScript are stored in 64-bit format IEEE-754
, also known as “double precision”.
You can normally write numbers as 1000000000
, but you can also shorten the number using the symbol e
. Here are few example -
// Something very big - // 1e3 = 1 * 1000 // 1.23e6 = 1.23 * 1000000 let billion = 1e9; // 1 billion, literally: 1 and 9 zeroes alert( 7.3e9 ); // 7.3 billions (7,300,000,000) // Something very small - // 1e-3 = 1 / 1000 (=0.001) // 1.23e-6 = 1.23 / 1000000 (=0.00000123) let ms = 1e-6; // six zeroes to the left from 1, which is 0.000001;
The method num.toString(base)
returns a string representation of num in the numeral system with the given base. The base can vary from 2 to 36. By default it’s 10.
let num = 255; alert( num.toString(16) ); // ff alert( num.toString(2) ); // 11111111 alert( 123456..toString(36) ); // 2n9c
Please note that two dots in 123456..toString(36)
is not a typo. If we want to call a method directly on a number, like toString
in the example above, then we need to place two dots ..
after it.
If we placed a single dot: 123456.toString(36)
, then there would be an error, because JavaScript syntax implies the decimal part after the first dot. And if we place one more dot, then JavaScript knows that the decimal part is empty and now goes the method.
Also could write -
alert((123456).toString(36));
One of the most used operations when working with numbers is rounding. The inbuilt object Math
provides many methods to deal with numbers -
The floor()
method rounds a number DOWNWARDS to the nearest integer, and returns the result. If the passed argument is an integer, the value will not be rounded.
var a = Math.floor(0.60); //0 var b = Math.floor(0.40); //0 var c = Math.floor(5); //5 var d = Math.floor(5.1); //5 var e = Math.floor(-5.1); //-6 var f = Math.floor(-5.9); //-6
The ceil()
method rounds a number UPWARDS to the nearest integer, and returns the result. If the passed argument is an integer, the value will not be rounded.
var a = Math.ceil(0.60); // 1 var b = Math.ceil(0.40); // 1 var c = Math.ceil(5); // 5 var d = Math.ceil(5.1); // 6 var e = Math.ceil(-5.1); // -5 var f = Math.ceil(-5.9); // -5
The round()
method rounds a number to the nearest integer.
var a = Math.round(2.60); // 3 var b = Math.round(2.50); // 3 var c = Math.round(2.49); // 2 var d = Math.round(-2.60); // -3 var e = Math.round(-2.50); // -2 var f = Math.round(-2.49); // -2
The trunc()
method returns the integer part of a number. This method will NOT round the number up/down to the nearest ingeger, but simply remove the decimals.
Math.trunc(8.76); // 8 Math.trunc(-3.76); // -3
Return a random number between 0 and 1.
alert( Math.random() ); // 0.1234567894322 alert( Math.random() ); // 0.5435252343232 alert( Math.random() ); // ... (any random numbers)
If you want to get random number between 1 to 10, then multiply the number by 10 and then add 1 :
Math.floor((Math.random() * 10) + 1);
Returns the greatest from the arbitrary number of arguments.
alert( Math.max(3, 5, -10, 0, 1) ); // 5
Returns the smallest from the arbitrary number of arguments.
alert( Math.min(1, 2) ); // 1
Returns n
raised the given power
alert( Math.pow(2, 10) ); // 2 in power 10 = 1024
The method toFixed(n)
rounds the number to n
digits after the point and returns a string representation of the result.
let num = 12.34; alert( num.toFixed(1) ); // "12.3" let num = 12.36; alert( num.toFixed(1) ); // "12.4"
Please note that result of toFixed
is a string. If the decimal part is shorter than required, zeroes are appended to the end:
let num = 12.34; alert( num.toFixed(5) ); // "12.34000", added zeroes to make exactly 5 digits
These are special number.
Infinity
(and -Infinity
) is a special numeric value that is greater (less) than anything.NaN
represents an error. The value NaN
is unique in that it does not equal anything, including itself:They belong to the type number, but are not “normal” numbers, so there are special functions to check for them:
alert( NaN === NaN ); // false alert( isNaN(NaN) ); // true alert( isNaN("str") ); // true
isFinite(value)
converts its argument to a number and returns true if it’s a regular number, not NaN
/Infinity
/-Infinity
:
alert( isFinite("15") ); // true alert( isFinite("str") ); // false, because a special value: NaN alert( isFinite(Infinity) ); // false, because a special value: Infinity
Sometimes isFinite is used to validate whether a string value is a regular number. Please note that an empty or a space-only string is treated as 0 in all numeric functions including isFinite.
isFinite(" "); // true isFinite("0"); // true
There is a special built-in method Object.is
that compares values like ===
, but is more reliable for two edge cases:
Object.is(3, 3); // true Object.is(100.5678, 100.5678); // true Object.is(3, 5); // false Object.is(true, false); // false Object.is(true, true); // true Object.is(NaN, NaN); // true Object.is(Infinity, Infinity); // true
This way of comparison is often used in JavaScript specification. When an internal algorithm needs to compare two values for being exactly the same, it uses Object.is