JavaScript Concepts Every Beginner Should Know

If you want to code in JavaScript, it’s important to fully master the fundamentals about the language first, especially if you want to avoid hours of painful debugging later. JavaScript has its fair share of quirks, so I will explain in detail here a few of the key concepts every beginner should know, such as objects, array methods, variables as pointers, and truthiness.

Objects

Objects consist of a collection of key-value pairs, each key denoting a property. We can access a value by referencing its key. We can also reassign the value stored at a given key, and add and remove keys from objects. Therefore, objects are mutable, unlike primitive types.

Object keys are always strings. Even if we try to assign a number as a key (such as 5), the number will be coerced into a string (5 => ‘5’). Object keys are also called properties.

Objects can be initialized with curly braces, like this:let person = {};. Here we are declaring a variable named person and assigning it an empty object.

We access and assign new values to an object by using dot notation or bracket notation.

Dot notation:

person.age = 25;
console.log(person.age) // returns 25

Bracket notation:

person['age'] = 25;
console.log(person['age']) // returns 25

We can re-assign the value for the age property in a similar manner.

person['age'] = 30;
console.log(person['age']) // returns 30

What if we want to see all of the object’s keys, or all of the object’s values? There are several methods for doing so.

Object.keys(person) returns an array of the keys in the person object.

Object.values(person) returns an array of the values in the person object.

To iterate through each key we can use a for loop. In the code snippet below, I am using a for...in loop, which iterates over the keys of an object. Inside the loop, the key is logged (using string interpolation) in the first line. On the next line, the value associated with that key is accessed through bracket notation, and logged to the console.

for (let key in person) {
console.log(`Key: ${key}`);
console.log(`Value: ${person[key]}`);
}

When we run this code, we get the output below:

Key: name
Value: Bob
Key: age
Value: 25
Key: eyeColor
Value: brown

One important distinction is that objects do not behave the same as primitive data types. A variable assigned to an object doesn’t just store a copy of the object, like it would for the number 5. Rather, the object is stored somewhere else in memory, and the variable points to that address location in memory. If we try to make a copy of the variable, the new variable will just point to the same object in memory. Thus, any changes made to the copy will also be made to the original. Let’s look at an example:

let person = {name: 'Jessica', age: 25, eyeColor: 'brown'};
let copyOfPerson = person;
copyOfPerson.name = 'Bob';
console.log(person.name); // person.name is now 'Bob'

To explain the code snippet above, we first initialize an object literal called person, containing a name property, an age property, and an eyeColor property. On line 2, we initialize a new variable named copyOfPerson, and assign to it the person variable. On line 3, we reassign the value in the name property of the copied variable to ‘Bob’. Will it change the original person object as well?

On line 4, we log the value at the name property of the person object. It logs ‘Bob’! This means that the original was changed even when we only modified the copy, demonstrating that both variables were pointing to the same object in memory.

This is why we should be very careful what changes we make to objects, in order to avoid unintended errors. We can use the Object.freeze() method to prevent objects’ properties from being modified (however, that method only works one level deep).

Arrays

Arrays are an ordered list of elements that can be accessed by index. Arrays are also objects. Since they are objects, they are also mutable. This means we can add, remove, and reassign values in arrays in the same way that we can for objects. Also like objects, when a variable is assigned an array, the variable acts as a pointer to the array in memory. Here is an example showing that a function can mutate a global variable:

let a = [1, 2, 3, 4, 5];function removeElement(arr) {
arr.pop();
return arr;
}
removeElement(a);
console.log(a);
// [1, 2, 3, 4]

We first declare an array assigned to the variable a. We also define a function that has one parameter arr (an array), and performs the pop method on the local arr variable, which contains a reference. We invoke the removeElement function, passing in a (which is the reference to [1, 2, 3, 4, 5] ) as the argument. If we had passed in a primitive data type like a string or number as the argument, then a copy of the value itself would be passed in so the function could not change the value of the global variable. After running the console.log(a) statement, we see that a was indeed mutated by the removeElement function.

Now, we declare a constant variable named grades, containing an array of six integers. Constant variables cannot be assigned, but can this array be mutated?

const grades = [100, 90, 80, 70, 60, 50];
grades.pop();
console.log(grades);
// [100, 90, 80, 70, 60]

Using the pop() method, we attempt to remove the last element from the array. Interestingly, it successfully removes the element, even though we declared grades with const. This is because we are only changing elements inside of the array, which const allows, not pointing to a new location. If we tried to reassign the constant variable grades to a completely new array, that would not work. *Note that the code snippe above was for illustrative purposes — modifying constant variables like this is NOT recommended.

Arrays are different from objects in that they come with a length property, and only the values at the numeric indexes within their length are considered real elements. We can change the length property’s value by explicitly reassigning it to a new number, or by adding or removing elements to the array.

JavaScript has a great collection of higher order array methods that are extremely useful. Here I will describe the forEach method and the some method, although there are plenty of others.

Array.prototype.forEach()

The forEach method takes in a callback function as its parameter, and executes the function for every element in the array. The callback function takes an element parameter, as well as optional parameters for the index and array. The element argument represents the current element of the array as the array is iterated over with increasing index. The body of the function performs some action using that element. The callback function is invoked once for each element (that’s why it’s called “forEach”!). After the callback function invocations finish, the forEach method returns undefined.

Below is an example using forEach to interleave two arrays into a new array while maintaining their order.

let arr1 = [1, 2, 3];
let arr2 = ['a', 'b', 'c'];
let result = [];
arr1.forEach((element, idx) => {
result.push(element);
result.push(arr2[idx]);
});
console.log(result) // [1, "a", 2, "b", 3, "c"]

First, we declare two arrays, arr1 and arr2, which we want to combine into a new array, which we initialized in the result variable. Then, the forEach method is invoked on arr1. We pass in a callback function, and inside that callback function, we supply two arguments. The index parameter is optional, but used in this example. Inside of the callback function, we push the current element to the result array, and then push the element at the current index of arr2 to the result array. This callback function is invoked 3 times since there are 3 elements in arr1. The callback function is invoked with the array’s elements in order like this:

(element = 1, index = 0) => result.push(1); result.push("a");
(element = 2, index = 1) => result.push(2); result.push("b");
(element = 3, index = 2) => result.push(3); result.push("c");

In conclusion, the forEach method is incredibly useful for a wide variety of use cases involving arrays.

Array.prototype.some()

The some method also takes in a callback function as its parameter, and it returns true if any element in the array meets the condition provided by the callback function.

How the callback function works is that it takes in the current element as the argument, with optional arguments for index and array. The element argument represents the current element of the array as the array is iterated over with increasing index. The body of the function tests some condition and returns a value that can be truthy or falsy. If the return value is truthy, then the some method immediately returns true. If none of the callback function invocations return a truthy value, the some method returns false.

Below is an example illustrating the usage of this method on an array:

let words = ['ant', 'bear', 'bat', 'cat', 'dog'];let result1 = words.some((element) => element.includes('at'));
console.log(result1); // true
let result2 = words.some((element) => element.includes('z'));
console.log(result2); // false

In the code snippet above, we first declare a variable named words and assign it an array of strings. We then call the some method on the words array.

In the first method call’s callback function, we test for whether the current element includes the substring “at”. Since “bat” contains this substring, the callback function returns true for that element. Then, the some method returns true, which is logged to the console.

In the second method call’s callback function, we test for whether the current element includes the substring “z”. The callback function executes for every string in the array, but returns false for each. Since none of the return values were truthy, the secondsome method returns false.

There are several other great array methods that I will not go into here, such as map, filter, reduce, find, and every, but they can all be found on the MDN Web Docs.

Truthiness

So what does it mean when we say “truthy” and “falsy”? Firstly, these adjectives have different meanings from “true” and “false”. true and false are the two Boolean values. On the other hand, falsy values include false, 0, NaN, "", undefined, and null. All other values are truthy, such as “dog”, 15, and true. All truthy values evaluate to true, and all falsy values evaluate to false. However, this does not mean that truthy values are equal to true, or that falsy values are equal to false!

Let’s look at an example below. We declare a variable named word and assign it the string value “false”. The conditional statement on line 2 tests for the truthiness of the variable word. If the statement evaluates to a truthy value, then line 3 is executed. Otherwise, the else statement in line 5 is executed.

let word = "false";
if (word) {
console.log(`${word} is truthy`);
} else {
console.log(`${word} is falsy`);
}

This outputs “false is truthy”. This is because “false” is a string, not the Boolean value false. Non-empty strings are always truthy, no matter what word is inside the string. So in line 2, when the conditional statement evaluates the truthiness of the word variable, word is truthy, so the statement evaluates to true. Thus, line 3 is the statement that executes.

Let’s look at another example: we declare a variable named number and assign it the value 0. We then test the condition number === false, which evaluates to 0 === false. If the condition returns a truthy value, line 3 is executed. If not, the else statement on line 5 is executed.

Now what do you think the below code snippet will output after the conditional statement on line 2?

let number = 0;
if (number === false) {
console.log(`${number} is equal to false`);
} else {
console.log(`${number} is not equal to false`);
}

The code above outputs “0 is not equal to false” (from line 5). This means that the conditional statement on line 2 evaluated to false. Although 0 is falsy, it is not strictly equal to false. However, if we used the == operator instead, then the expression would evaluate to true due to type coercion.

As we have seen, it is important to distinguish whether we are looking for only a truthy/falsy value or the boolean values true/false, as they can lead to different results.

That’s it for now. Thanks for reading!