Tricky Parts of JavaScript I?-?Data Types vs Assignment & Equality Operators
Theodora Gyambrah
Passionate Software Engineer | Project Manager | Blockchain Developer | Engineering dreams - one line of code at a time
In the world of programming, JavaScript, like any language, has its fair share of tricky aspects that can stump developers. Whether you’re a seasoned pro or just starting out, these intricacies are bound to cross your path as you build web applications or tinker with server-side logic using Node.js. In this article and the next, we’ll explore some of these tricky elements.
So, let’s dive right?in.
1. Primitive vs. Reference Data Types and Assignment Behavior
In JavaScript, data types are broadly categorized into two classes: primitive data types, often referred to as “value data types,” and reference data types. These two categories exhibit distinct behaviors when it comes to assignment. Let’s delve into some examples to illuminate this concept:
// Example Set 1
let a = 5;
let b = a;
b = 10;
console.log(a); // Output: 5
console.log(b); // Output: 10
// Example Set 2
let str1 = "Hello";
let str2 = str1;
str2 += " World";
console.log(str1); // Output: "Hello"
console.log(str2); // Output: "Hello World"
// Example Set 3
let arr1 = [1, 2, 3];
let arr2 = arr1;
arr2.push(4);
console.log(arr1); // Output: [1, 2, 3, 4]
console.log(arr2); // Output: [1, 2, 3, 4]
// Example Set 4
let obj1 = { name: "Ivan" };
let obj2 = obj1;
obj2.name = "Esther";
console.log(obj1.name); // Output: "Esther"
console.log(obj2.name); // Output: "Esther"
Example Sets 1 & 2?—?Primitive Values (Number and?String)
In these set of examples, we’re working with primitive values of the Number and String data types, which belong to the category of Primitive Data Types. JavaScript also includes other primitive data types, such as booleans, null, undefined, symbols, and BigInt.?
Let’s look at three characteristics of Primitive Data types which are essential to understanding the behaviors in these two set examples:?
In the example set 1,?
Similarly, with strings in example set 2,
Example Sets 3 & 4— Reference Types(Arrays and?Objects)
In these examples, we are dealing with Arrays and Objects which are Reference data types. Other examples are Functions and Classes. Here are some key characteristics of reference data types:
In example set 3,
In example set 4,
领英推荐
2. Equality Operators
JavaScript has two types of equality operators: == (loose equality) and ===(strict equality). These operators can be tricky, as they don’t always behave as one might expect, particularly when comparing different data types or values.
Let’s explore both and see how they can be tricky with some examples:
// Example Set 1
1 == '1'; // true (string '1' is coerced to a number for comparison)
0 == false; // true (coerces boolean to number for comparison)
"0" == false; // true (both are coerced to number 0)
null == undefined; // true (both are considered equal in ==)
// Example Set 2
1 === '1'; // false (number is not equal to string)
0 === false; // false (number is not equal to boolean)
"0" == false; // false (string is not equal to boolean)
null === undefined; // false (different data types)
To understand these behaviors, let’s dive deeper into each operator type:
Loose Equality?(==):?
The loose equality operator compares values while allowing type coercion, meaning it attempts to convert the values into a common type before making the comparison. This can lead to unexpected results, making it generally advisable to avoid its use.
In the first example set, the operands are coerced to the same data type before the comparison, hence returning true for all comparisons.
Strict Equality?(===):
The strict equality operator, on the other hand, compares values for equality without performing type coercion. It checks not only the value but also the data type. This typically leads to more predictable results.?
In the second example set, the operands aren’t coerced, and their data types are explicitly considered, leading to false results for all comparisons.
Note: Comparing Reference Data?Types
When comparing reference data types, such as arrays and objects, JavaScript’s equality operators check if the references point to the same data in memory, not if their content is the same.
//Will Return False
const arr1 = [1, 2, 3];
const arr2 = [1, 2, 3];
arr1 == arr2; // false (arrays are compared by reference, not by content)
arr1 === arr2; // false (for the same reason as above)
const obj1 = { key: "value" };
const obj2 = { key: "value" };
obj1 == obj2; // false (objects are compared by reference, not by content)
obj1 === obj2; // false (for the same reason as above)
//Will Return True
const arr1 = [1, 2, 3];
const arr2 = arr1; // arr2 reference the same array as arr1
arr1 == arr2; // true (both variables reference the same array)
arr1 === arr2; // true (for the same reason as above)
const obj1 = { key: "value" };
const obj2 = obj1; // obj2 reference the same object as obj1
obj1 == obj2; // true (both variables reference the same object)
obj1 === obj2; // true (for the same reason as above)
For comparing the content of reference data types, you’ll usually need to iterate through their properties or elements to check for equality. Alternatively, you can serialize objects to JSON strings with JSON.Stringify( ) and compare those strings, or use libraries like lodash or Underscore.js, which offer the isEqual( ) utility function for such comparisons.
In Summary,
In this article, we uncovered some intricacies of primitive and reference data types and their corresponding behaviors with respect to assignment operators. We’ve also delved into the nuances of equality operators and how they can lead to unexpected results.
But our journey is far from over! Stay tuned for the next article where we’ll dive into scope and hoisting, shedding light on how hoisting can sometimes lead to surprising behavior. Additionally, we’ll explore the immutability of variables created with const and how it can affect your code.