Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why to avoid creating objects of primitives in JavaScript?

Tags:

javascript

I am following a JavaScript tutorial on W3Schools. While reading almost on each page they give note to user to "Avoid creating objects" and to use primitive data types instead. They give reason for this as "code becomes difficult to understand or execution speed will be decreased if object are used". Is it true that we should avoid creating objects in JavaScript?

For example:

var value = new Number(1);  // Avoid this var value = 1;              // do something like this instead. 
like image 699
WeAreRight Avatar asked Jan 04 '17 07:01

WeAreRight


People also ask

Why would you use the object create () method to create an object?

The Object. create() method creates a new object, using an existing object as the prototype of the newly created object.

Should you use objects in JavaScript?

Objects in programming can be a combination of variables, functions, and data structures. This means that objects can store values, you can use objects to manipulate values and combine them into more complex objects, like arrays and still get all the benefits. JavaScript is no different.

Why do we create object in JavaScript?

We all deal with objects in one way or another while writing code in a programming language. In JavaScript, objects provide a way for us to store, manipulate, and send data over the network. There are many ways in which objects in JavaScript differ from objects in other mainstream programming languages, like Java.


2 Answers

The statement "avoid creating objects" on its own is absurd in JavaScript, which has objects everywhere and is one of the most object-oriented languages in existence. But "avoid creating object versions of primitives," which is what the code you quote does, is valid. That is, avoid new String, new Number, and new Boolean.

JavaScript has both primitive and object versions of strings, numbers, and booleans. There's almost never any reason to create the object version of any of them explicitly, and doing so can indeed lead to confusion; see inline comments:

var s1, s2, n1, n2;    // These are false because with ===, an object is never equal to a non-object  s1 = new String("hi");  s2 = "hi";  console.log(s1 === s2); // false  n1 = new Number(42);  n2 = 42;  console.log(n1 === n2); // also false    // These are false because even with ==, two *different* objects are never equal  // (even if they're equivalent)  s1 = new String("what the...");  s2 = new String("what the...");  console.log(s1 == s2);  // also false  n1 = new Number(42);  n2 = new Number(42);  console.log(n1 == n2);  // also false

The object versions of strings, numbers, and booleans largely exist to enable methods on primitives to be provided using the same mechanism that provides methods to object types. When you do

console.log("foo".toUpperCase()); // "FOO" 

a temporary object is created for the primitive string "foo", and then the toUpperCase property is read from that object. Since the object inherits from String.prototype, it has toUpperCase and all is well. Once the operation is done, the temporary object is thrown away (unless something keeps a reference to it, but nothing does and nothing can with toUpperCase, you'd have to add a method to String.prototype that returned the object in order for it to be kept around).

like image 185
T.J. Crowder Avatar answered Oct 04 '22 15:10

T.J. Crowder


It changes the intuitive way the operators behave with numbers, strings and booleans:

  • the strict comparison (===) breaks when any of the numbers is constructed, so 42 === 42 is true, while 42 === new Number(42) is not,
  • the abstract comparison (==) breaks when both numbers are objects, so 42 == new Number(42) is true, while new Number(42) == new Number(42) is not,
  • the typeof operator gives different result when a number is constructed, so typeof(42) is number, but typeof(new Number(42)) is object,
  • when converted to a boolean, 0 is false, but new Number(0) is true, so the following two will have different behavior:

var a = 0;  if (a)    console.log("not zero");  else    console.log("zero!");     // "zero!"    var b = new Number(0);  if (b)    console.log("not zero");     // "not zero"  else    console.log("zero!");

So, avoid new Number, new String and new Boolean.

Apart from that, there is the issue of using / not using new with constructors. It stems from several facts:

  • in JS, a constructor is a regular function, using this.foo syntax to add new properties and methods;
  • when invoked without the new keyword, this becomes the global object, leading to side effects.

As a result, a tiny mistake can have catastrophic effects:

color = "blue";    var Fruit = function(color) {    this.color = color;    return this;  };    var apple = new Fruit("green");    console.log(apple.color);       // "green"  --  okay    console.log(color);             // "blue"  --  okay    var banana = Fruit("yellow");    console.log(banana.color);      // "yellow"  --  okay    console.log(color);             // "yellow"  --  wait, what?    console.log(banana.apple);      // "{ color: 'green' }"  --  what??    console.log(banana.document);   // "{ location: [Getter/Setter] }"  --  what???

(That's why some people resort to adding explicit checks in the constructor, or using closures instead. But that's for another story.)

like image 40
M. M. Avatar answered Oct 04 '22 14:10

M. M.