14 mysterious JavaScript features worth knowing

14 mysterious JavaScript features worth knowing

· 4 min read
Contents

      JavaScript is a powerful and flexible programming language, but it also has some unique features and behavior that can be considered "weird" or "non-intuitive" to some developers. Here are a few examples:

      Automatic type coercion:

      JavaScript is a loosely typed language, which means that the interpreter will automatically convert values from one type to another when necessary. This can lead to unexpected results, for example:

      console.log(1 + "2");  // "12" (string concatenation)
      console.log([] + []); // "" (empty string)
      console.log([1,2,3] == "1,2,3"); // true (type coercion)

      Equality comparison:

      JavaScript has two types of equality comparison: "==" and "===". The "==" operator performs type coercion if necessary, while the "===" operator compares values without coercion. This can lead to unexpected results, for example:

      console.log(1 == true);  // true (type coercion)
      console.log(1 === true); // false (no coercion)
      console.log(null == undefined); // true
      console.log(null === undefined); // false

      Hoisting:

      In JavaScript, variable and function declarations are "hoisted" to the top of their scope, which means that they are accessible before they are declared. This can lead to unexpected results, for example:

      console.log(x);   // undefined (x is hoisted)
      var x = 1;
      
      console.log(y);   // ReferenceError: y is not defined
      let y = 1;
      

      Global variables:

      In JavaScript, variables that are not declared inside a function are considered global variables and are accessible from anywhere in the code. This can lead to naming conflicts and unexpected results, for example:

      var x = 1;
      function test() {
        console.log(x);   // 1 (x is global)
      }
      test();
      

      The 'this' keyword:

      In JavaScript, the value of this keyword is determined by how a function is called, not where it is defined. This can lead to unexpected results, for example:

      const obj = {
        name: "John",
        printName: function() {
          console.log(this.name);
        }
      };
      
      const print = obj.printName;
      print();  // undefined (this is not bound to obj)
      

      Function scope:

      In JavaScript, function scope is used instead of block scope. This can lead to unexpected results, for example:

      for (var i = 0; i < 3; i++) {
        setTimeout(function() {
          console.log(i);
        }, 100);
      }
      // 3 3 3 (i is in the same scope)
      
      for (let i = 0; i < 3; i++) {
        setTimeout(function() {
          console.log(i);
        }, 100);
      }
      // 0 1 2 (i is in different scope)
      

      Prototype-based inheritance:

      JavaScript is a prototype-based language, which means that objects inherit properties and methods from other objects through prototypes. This can be different from traditional class-based inheritance and can lead to unexpected results, for example:

      const animal = {
        eats: true,
        walk() {
          console.log("Animal can walk");
        }
      };
      const rabbit = Object.create(animal);
      rabbit.jumps = true;
      console.log(rabbit.eats);  // true (inherited from animal)
      console.log(rabbit.jumps); // true (defined on rabbit)
      

      Automatic semicolon insertion:

      JavaScript's automatic semicolon insertion (ASI) feature can lead to unexpected results if not used correctly. For example:

      const x = 5
      console.log(x) // 5
      

      In this example, JavaScript inserts a semicolon after the const x = 5 statement, which is treated as a separate statement from the console.log(x). As a result, x is assigned the value 5 instead of the intended console.log(x) statement.

      Function expressions vs function declarations:

      The difference in how they are handled by JavaScript's hoisting feature can lead to unexpected results if not used correctly. For example:

      foo(); // ReferenceError
      
      const foo = function() {
        console.log('bar');
      };
      
      

      In this example, the function is assigned to a variable foo but due to hoisting the variable is hoisted but the assignment is not and thus the reference error.

      The NaN value:

      JavaScript has a special NaN value, which stands for "not a number." When a mathematical operation cannot produce a valid number, it returns NaN. This can lead to unexpected results, for example:

      console.log(0 / 0); // NaN
      console.log(isNaN(NaN)); // true
      console.log(NaN == NaN); // false
      

      Implicit type conversion:

      JavaScript can perform implicit type conversion in certain situations, such as when comparing values or using certain operators. For example:

      console.log("5" == 5); // true
      console.log("5" === 5); // false
      console.log(true + 1); // 2
      console.log([] + {}); // "[object Object]"
      

      In these examples, JavaScript performs an implicit type conversion, which can lead to unexpected results if not taken into account.

      Property access on null and undefined:

      In JavaScript, trying to access a property on a null or undefined value will not throw an error, but instead will return undefined. For example:

      console.log(null.x); // undefined
      console.log(undefined.x); // undefined
      console.log({}.x); // undefined
      

      In these examples, trying to access a property on a null or undefined value will not throw an error, but it can lead to unexpected results if not handled properly.

      The == operator:

      JavaScript's == operator compares values for equality, but it can perform type coercion if the operands are of different types. This can lead to unexpected results, for example:

      console.log('' == 0); // true
      console.log(null == undefined); // true
      console.log([] == false); // true
      

      In these examples, JavaScript's == operator performs type coercion and returns true even though the values are not equal in the traditional sense.

      Function scope:

      JavaScript uses function scope, which means that variables declared within a function are only accessible within that function. However, variables declared with the var keyword are also accessible within the entire function scope, which can lead to unexpected results. For example:

      function test() {
        var x = 1;
        if (true) {
          var x = 2;
          console.log(x); // 2
        }
        console.log(x); // 2
      }
      test();
      

      In this example, the variable x is declared twice within the same function scope, and the second declaration overwrites the first. This can lead to unexpected results if not handled properly.

      Conclusion:

      These are examples of unique features and behavior of JavaScript that can be considered "weird" or "non-intuitive" to some developers. Understanding these features can help you write more efficient and effective code, and avoid potential bugs in your JavaScript programs.

      Stay updated

      Get new posts delivered to your inbox.