javascript

How to Fix the “Cannot access before initialization” Reference Error in JavaScript

The “cannot access before initialization” reference error occurs in JavaScript when you try to access a variable before it is declared with let or const and initialized in the same scope. To fix it, initialize the variables before accessing them.

The "cannot access before initialization" reference error occurring in JavaScript.
The “cannot access before initialization” reference error occurring in JavaScript.

Here are some examples of the error occurring:

index.js
// โŒ ReferenceError: Cannot access 'num' before initialization console.log(num); let num = 2; // โŒ ReferenceError: Cannot access 'name' before initialization console.log(name); const name = 'Coding Beauty'; // โŒ ReferenceError: Cannot access 'arr' before initialization arr = [7, 8, 9]; let arr = [3, 4, 5]; ๏ปฟ

To solve the error, you need to initialize the variable before accessing it.

index.js
// โœ… No error let num = 2; console.log(num); // 2 // โœ… No error const name = 'Coding Beauty'; console.log(name); // Coding Beauty // โœ… No error let arr = [3, 4, 5]; arr = [7, 8, 9];

var vs let

The occurrence of this error shows an important difference between the var and let keywords. If you had declared the variable with var, the error wouldn’t have occurred.

index.js
// No error console.log(num); // undefined var num = 2; // No error console.log(name); // undefined var name = 'Coding Beauty'; // No error arr = [7, 8, 9]; var arr = [3, 4, 5];

This happens because variables declared with the var keyword are hoisted – they are moved by the JavaScript interpreter to the top of the current scope (to the top of the current script or current function).

Basically, this is what happens to our variables declared with var:

index.js
var num; var name; var arr; console.log(num); // undefined num = 2; console.log(name); // undefined name = 'Coding Beauty'; arr = [7, 8, 9]; arr = [3, 4, 5];

Note: The declarations are hoisted, but the initializations are not.

Because of this hoisting, even when the variable is declared in a non-function block, like an if block, the error will still not occur if you try to access the variable from outside the if statement.

index.js
// No error! console.log(num); // undefined if (true) { var num = 2; }

Only the global scope and function scopes are used for hoisting, so like before, the variable declaration is moved to the top of the file.

index.js
var num; console.log(num); // undefined if (true) { num = 2; }

How to Convert Seconds to Hours and Minutes in JavaScript

To convert seconds to hours and minutes in JavaScript:

  1. Divide the seconds by 60 to get the total minutes. The remainder will be the seconds in the output.
  2. Divide the total minutes by 60 to get the hours. The whole number in the result will be the hours, and the remainder will be the minutes in the output.

For example:

function toHoursAndMinutes(totalSeconds) {
  const totalMinutes = Math.floor(totalSeconds / 60);

  const seconds = totalSeconds % 60;
  const hours = Math.floor(totalMinutes / 60);
  const minutes = totalMinutes % 60;

  return { h: hours, m: minutes, s: seconds };
}

// { h: 0, m: 1, s: 0 }
console.log(toHoursAndMinutes(60));

// { h: 0, m: 16, s: 40 }
console.log(toHoursAndMinutes(1000));

// { h: 1, m: 10, s: 50 }
console.log(toHoursAndMinutes(4250));

We create a reusable function that takes a total number of seconds and returns an object containing the separate hours, minutes, and seconds values.

First, we divide the total seconds by 60 to get the number of total minutes.

console.log(60 / 60); // 1

console.log(1000 / 60); // 16.666666666666668

console.log(4250 / 60); // 70.83333333333333

The division results in a decimal number, so we use the Math.floor() function to get just the whole number of the result.

Math.floor() returns the largest integer less than or equal to a specified number.

console.log(Math.floor(10.95)); // 10
console.log(Math.floor(10)); // 10
console.log(Math.floor(10.05)); // 10

After this, we use the modulo operator (%) to get the division’s remainder for the seconds in the result.

console.log(60 % 60); // 0

console.log(1000 % 60); // 40

console.log(4250 % 60); // 50

Tip: Skip this step if the seconds should not be in the result.

We all know 60 seconds make a minute, and 60 minutes make an hour. After getting the total minutes, we do something similar to what we just did to the total seconds value: we divide the total minutes by 60 to get the hours and use the module operator to get the division’s remainder, which will be the minutes in the output.

After getting all the values, we return an object with h, m, and s properties containing the hours, minutes, and seconds respectively.

return { h: hours, m: minutes, s: seconds };

Convert seconds to HH:mm:ss

Instead of an object, you might want the result to be a time string in a format like HH:mm:ss, where each value is separated by a colon and has a minimum of two digits in the string. Here’s how we can produce such a time string.

function toTimeString(totalSeconds) {
  const totalMs = totalSeconds * 1000;
  const result = new Date(totalMs).toISOString().slice(11, 19);

  return result;
}

console.log(toTimeString(60)); // 00:01:00

console.log(toTimeString(1000)); // 00:16:40

console.log(toTimeString(4250)); // 01:10:50

First, we convert the seconds to milliseconds to pass it to the Date() constructor and create a new Date object.

The Date toISOString() method returns a string representation of the date in the ISO 8601 format, i.e., YYYY-MM-DDTHH:mm:ss.sssZ

const totalMs = 60000;

// 1970-01-01T00:01:00.000Z
console.log(new Date(totalMs).toISOString());

You can see that toISOString() does the conversion for us. We just need a way to extract the HH:mm:ss from the ISO string.

The String slice() method returns the portion of a string between specified start and end indexes, passed as the first and second arguments respectively.

The HH:mm:ss starts at index 11 of the string and ends at index 18. So to extract it, the values we pass to slice() or substring() will be 11 and 19.

Tip: 19 because slice() excludes the character at the end index from the resulting substring.

// 00:01:00
console.log('1970-01-01T00:01:00.000Z'.slice(11, 19));

To exclude the seconds from the result, we just need to reduce the end index by 3 to exclude the colon and the digits of the seconds.

// 00:01
console.log('1970-01-01T00:01:00.000Z'.slice(11, 16));

How to Capitalize the First Letter of a String in Vue.js

To capitalize the first letter of a string in Vue:

  1. Get the string’s first letter with [0].
  2. Uppercase this letter with .toUpperCase().
  3. Get the rest of the string with .slice(1).
  4. Add the results together.

For example:

App.vue

<template>
  <div id="app">
    <b>{{ name1 }}</b>
    <br />
    Capitalized: <b>{{ capitalized(name1) }}</b>
    <br /><br />
    <b>{{ name2 }}</b
>
    <br />
    Capitalized:
    <b>{{ capitalized(name2) }}</b>
  </div>
</template>

<script>
export default {
  data() {
    return { name1: 'coding beauty', name2: 'javascript' };
  },
  methods: {
    capitalized(name) {
      const capitalizedFirst = name[0].toUpperCase();
      const rest = name.slice(1);

      return capitalizedFirst + rest;
    },
  },
};
</script>
The strings and their capitalized forms.
The strings and their capitalized forms.

We create a reusable Vue instance method (capitalized) that takes a string and capitalizes its first letter.

We use bracket indexing ([ ]) to get the 0 property of the string – the character at index 0. String (and array) indexing is zero-based in JavaScript, so the string’s first character is at index 0, the second is at index 1, and so on, until the last character at index str.length-1.

After getting the string’s first character, we uppercase it with the toUpperCase() method.

We use the slice() method to get the rest of the string. slice() returns the portion of a string between a specified start and an optional end index. If the end index is omitted, the substring will range from the start index to the end of the string.

Hence, slice(1) returns a substring ranging from the second character to the end.

After getting the remaining part of the string, all that’s left is simply concatenating it with the capitalized first letter.

If it’s necessary for the resulting string to have only its first letter capitalized, you can call the toLowerCase() method on the result of slice(), to lowercase the rest of the string before concatenation.

const capitalizedFirst = name[0].toUpperCase();

// ๐Ÿ‘‡ toLowerCase()
const rest = name.slice(1).toLowerCase();

return capitalizedFirst + rest;

Use Computed Property

If you’re trying to capitalize a string data property of the Vue instance (like in our example), you can use a computed property in place of a method.

<template>
  <div id="app">
    <b>{{ name1 }}</b>
    <br />
    Capitalized: <b>{{ capitalizedName1 }}</b> <br /><br />
    <b>{{ name2 }}</b
    ><br />
    Capitalized:
    <b>{{ capitalizedName2 }}</b>
  </div>
</template>

<script>
export default {
  data() {
    return { name1: 'coding beauty', name2: 'javascript' };
  },
  methods: {
    capitalized(name) {
      const capitalizedFirst = name[0].toUpperCase();
      const rest = name.slice(1);

      return capitalizedFirst + rest;
    },
  },

  // ๐Ÿ‘‡ Computed properties
  computed: {
    capitalizedName1() {
      return this.capitalized(this.name1);
    },
    capitalizedName2() {
      return this.capitalized(this.name2);
    },
  },
};
</script>

Using a computed property for this is useful when the data is likely to change in the app’s lifetime, e.g., in a two-way binding with an input field. When the data property changes, the depending computed property will be recalculated and updated automatically.

How to Capitalize the First Letter of Each Word in an Array in JavaScript

To capitalize the first letter of each word in an array in JavaScript:

  1. Iterate over the words array with .map().
  2. For each word, return a new word, the uppercased form of the word’s first letter added to the rest of the word.

For example:

function capitalizeWords(arr) {
  return arr.map((word) => {
    const capitalizedFirst = word.charAt(0).toUpperCase();
    const rest = word.slice(1).toLowerCase();
    return capitalizedFirst + rest;
  });
}

const words = ['welcome', 'to', 'CODING', 'Beauty'];

// [ 'Welcome', 'To', 'Coding', 'Beauty' ]
console.log(capitalizeWords(words));

Our capitalizeWords() function takes an array of words and returns a new array with all the words capitalized, without mutating the original array.

Firstly, we call the map() method on the array, passing a callback function as an argument. This function will be called and return a result for each word in the array.

In the callback, we get the word’s first character with charAt(), convert it to uppercase with toUpperCase(), and concatenate it with the rest of the string.

We use the String slice() method to get the remaining part of the string. Passing 1 to slice() makes it return the portion of the string from the second character to the end.

Note: String (and array) indexing is zero-based JavaScript, so the first character in a string is at index 0, the second at 1, and the last at str.length-1

After capitalizing the word, we lowercase it with the String toLowerCase() method. You can remove this toLowerCase() call if it’s not necessary for the non-first letter of each word in the array to be capitalized.

How to Capitalize the First Letter of Each Word in a String in JavaScript

To capitalize the first letter of each word in a string in JavaScript:

  1. Split the string into an array of words with .split('').
  2. Iterate over the words array with .map().
  3. For each word, return a new word that is an uppercase form of the word’s first letter added to the rest of the word.
  4. Join the words array into a string with .join(' ').

For example:

index.js

function capitalizeWords(str) {
  return str
    .toLowerCase()
    .split(' ')
    .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
    .join(' ');
}


// Welcome To Coding Beauty
console.log(capitalizeWords('WELCOME to coding beauty'));

// JavaScript And TypeScript
console.log(capitalizeWords('JAVASCRIPT AND TYPESCRIPT'));

Our capitalizeWords() function takes a string and returns a new string with all the words capitalized.

First, we use the toLowerCase() method to lowercase the entire string, ensuring that only the first letter of each word is uppercase.

// welcome to coding beauty
console.log('WELCOME to coding beauty'.toLowerCase());

Tip: If it’s not necessary for the remaining letters in each word to be lowercase, you can remove the call to the toLowerCase() method.

Then we call the String split() method on the string to split all the words into an array.

// [ 'welcome', 'to', 'coding', 'beauty' ]
console.log('welcome to coding beauty'.split(' '));

After creating the array, we call the map() method on it, with a callback function as an argument. This function will be called and return a result for each word in the array.

In the function, we get the word’s first character with charAt(), convert it to uppercase with toUpperCase(), and concatenate it with the rest of the string.

We use the String slice() method to get the remaining part of the string. Passing 1 to slice() makes it return the portion of the string from the second (index of 1) character to the end.

// [ 'Welcome', 'To', 'Coding', 'Beauty' ]
console.log(
  'welcome to coding beauty'
    .split(' ')
    .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
);

So map() returns an array containing all the words in the string, with each word’s first letter capitalized.

Lastly, we concatenate all the words in a single string, with the Array join() method.

Passing a space (' ') to join() separates the words by a space in the resulting string.

// Welcome To Coding Beauty
console.log(['Welcome', 'To', 'Coding', 'Beauty'].join(' '));

How to fix the “__dirname is not defined in ES module scope” error in JavaScript

The “__dirname is not defined in ES module scope” error happens in JavaScript when we try to access the __dirname global variable in an ES module. The __dirname and __filename global variables are defined in CommonJS modules, but not in ES modules.

The "__dirname is not defined in ES module scope" error occurring in JavaScript.
The “__dirname is not defined in ES module scope” error occurring in JavaScript.

We can fix the “__dirname is not defined in ES module scope” error by using certain functions to create a custom __dirname variable that works just like the global variable, containing the full path of the file’s current working directly.

index.js

import path from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);

const __dirname = path.dirname(__filename);

// C:/cb/cb-js
console.log(__dirname);

// C:\cb\cb-js\index.html
console.log(path.join(__dirname, 'index.html'));

The import.meta object contains context-specific metadata associated with a certain module, e.g., a module’s file URL.

// file:///C:/cb/cb-js/index.js
console.log(import.meta.url);

So we get the current module’s file URL and pass it to the fileURLToPath function from the url module, to convert it to a file path. fileURLToPath returns a fully-resolved, platform-specific Node.js file path.

// C:\cb\cb-js\index.js
console.log(fileURLToPath('file:///C:/cb/cb-js/index.js'));

After getting the file path, we pass it to the dirname method from the path module, to get the full directory path from the file path.

// C:\cb\cb-js
console.log(path.dirname('C:\\cb\\cb-js\\index.js'));

With this, we now have our own __dirname and __filename variables.

Here’s the output from logging them from a file on my computer.

Logging the "__dirname" and "__filename" variables to the console.
Logging the __dirname and __filename variables to the console.

__filename contains the absolute path of the current module file.

__dirname contains the absolute path of the current module file’s directory.

Create utility for __dirname and __filename

If we access the __dirname and __filename variables frequently, we can abstract the logic for creating them in a utility module and avoid unnecessary repetition.

file-dir-name.js

import { fileURLToPath } from 'url';
import { dirname } from 'path';

export default function fileDirName(meta) {
  const __filename = fileURLToPath(meta.url);

  const __dirname = dirname(__filename);

  return { __dirname, __filename };
}

We’ll be able to use this utility across the various other module files in our project.

index.js

import fileDirName from './file-dir-name.js';

const { __dirname, __filename } = fileDirName(import.meta);

// C:\cb\cb-js
console.log(__dirname);

// C:\cb\cb-js\index.js
console.log(__filename);

How to Use an Image as a Link in React

Related: How to Link an Image in React

To use an image as a link in React, wrap the image in an anchor (a) tag. Clicking an image link will make the browser navigate to the specified URL.

For example:

App.js

import cbLogo from './cb-logo.png';

export default function App() {
  return (
    <div>
      Click the logo to navigate to the site
      <br />
      <br />
      <a href="https://codingbeautydev.com" target="_blank" rel="noreferrer">
        <img src={cbLogo} alt="Coding Beauty logo"></img>
      </a>
    </div>
  );
}
The browser navigates to the URL when the image link is clicked.
The browser navigates to the URL when the image link is clicked.

We use an import statement to link the image into the file, and assign it to the src prop of the img element to display it.

The properties set on an a element will work as usual when it wraps an image. For instance, in the example, we set the a element’s target property to _blank, to open the URL in a new tab. Removing this will make it open in the same tab as normal.

We also set the rel prop to noreferrer for security purposes. It prevents the opened page from gaining access to any information about the page from which it was opened from.

For React Router, you can use an image as link by wrapping the image in a Link element.

For example:

ImagePages.jsx

import { Link } from 'react-router-dom';

export default function ImagesPage() {
  return (
    <div>
      <Link to="/nature" target="_blank" rel="noreferrer">
        <img src="/photos/tree-1.png" alt="Nature"></img>
      </Link>
    </div>
  );
}

How to Get an Input Field’s Value in React

To get the value of an input field in React:

  1. Create a state variable to store the input field’s value.
  2. Set an onChange event handler on the input field.
  3. In the event handler, assign event.target.value to the state variable.
  4. The state variable will contains the input field’s value at any given time.

For example:

App.js

import { useState } from 'react';

export default function App() {
  const [message, setMessage] = useState('');

  const [updated, setUpdated] = useState(message);

  const handleChange = (event) => {
    setMessage(event.target.value);
  };

  const handleClick = () => {
    //  "message" stores input field value
    setUpdated(message);
  };

  return (
    <div>
      <input
        type="text"
        id="message"
        name="message"
        onChange={handleChange}
        value={message}
      />

      <h2>Message: {message}</h2>

      <h2>Updated: {updated}</h2>

      <button onClick={handleClick}>Update</button>
    </div>
  );
}

With the useState hook, we create a state variable (message) to store the input field’s current value. We also create another state variable (updated) that will be updated with the input field value when the button is clicked.

We set an onChange event handler on the input field to execute an action. In the handler, we use the Event object’s target property to access the object representing the input element. The value property of this object contains the input value, so we pass it to setMessage to update message, and this reflects on the page.

After setting up the controlled input, we can now use message outside the handleChange handler to get the current value of the input field.

So in the onClick event handler we set on the button, we use setUpdated(message) to update the updated variable with the input field’s current value.

Get input value with ref

Alternatively, we can use a ref to get the value of an input field in React. After setting the ref on the input, we’ll be able to use the ref object to access the input field’s current value in the event handler.

App.js

import { useRef, useState } from 'react';

export default function App() {
  const inputRef = useRef(null);

  const [updated, setUpdated] = useState('');

  const handleKeyDown = (event) => {
    if (event.key === 'Enter') {
      setUpdated(inputRef.current.value);
    }
  };

  return (
    <div>
      <input
        ref={inputRef}
        type="text"
        id="message"
        name="message"
        onKeyDown={handleKeyDown}
      />

      <h2>Updated: {updated}</h2>
    </div>
  );
}

We set an onKeyDown event listener on the input to perform an action when a key is pressed. In this listener, we use the KeyboardEvent object’s key property to check if the key pressed is Enter, and if so, we use the ref object to get the input’s value and update the updated variable with it.

While the data in a controlled input is handled by React state, the data in an uncontrolled input is handled by the DOM itself. This is why the input in the example above doesnโ€™t have a value prop or onChange event handler set. Instead, we access the input field value with a React ref. The DOM updates this value when the text in the input is changed.

We create a ref object with the useRef hook and set it to the ref prop of the input. Doing this sets the current property of the ref object to the DOM object that represents the input element.

useRef returns a mutable ref object that does not change value when a component is updated. Also, modifying the value of this objectโ€™s current property does not cause a re-render. This is in contrast to the setState update function returned from useState.

Although the React documentation recommends using controlled components, uncontrolled components offer some advantages. You might prefer them if the form is simple and doesnโ€™t need instant validation, and values only need to be accessed on submission.

How to Check if a Checkbox is Checked in Vue.js

To check if a checkbox is checked in Vue:

  1. Create a boolean state variable to store the value of the checkbox.
  2. Use v-model to set up a two-way binding between the checkbox’s value and the state variable.
  3. If the checkbox is checked, the state variable will be true. Otherwise, it will be false.

For example:

App.vue

<template>
  <div id="app">
    <input
      type="checkbox"
      v-model="agreement"
      name="agreement"
    />

    <label for="agreement">
      I agree to the terms and conditions
    </label>

    <br /><br />

    <button :disabled="!agreement">Continue</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      agreement: false,
    };
  },
};
</script>
The button is disabled when the checkbox is checked, and enabled when it is unchecked.
The button is disabled when the checkbox is checked, and enabled when it is unchecked.

The checked property of the checkbox object indicates whether or not the checkbox is checked.

Every time the checkbox is checked or unchecked, the agreement state variable will be automatically updated to true or false respectively.

We set the button‘s disabled prop to the negation of agreement to disable and enable it when agreement is true and false respectively.

Check if checkbox is checked with ref

In most cases, v-model will be sufficient for checking if a checkbox if a checked in Vue. However, we can also use the ref attribute to get the input value. We can set this attribute on any DOM element and use the $refs property of the Vue instance to access the object that represents the element.

For example:

<template>
  <div id="app">
    <!-- ๐Ÿ‘‡ Set "ref" prop to create new ref -->
    <input
      type="checkbox"
      name="js"
      ref="theCheckbox"
    />

    <label for="js"> JavaScript </label>
    <br />
    <button @click="handleClick">Done</button>
    <p v-if="message">{{ message }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return { message: '' };
  },
  methods: {
    handleClick() {
      // ๐Ÿ‘‡ Access ref with "$refs" property
      if (this.$refs.theCheckbox.checked) {
        this.message = 'You know JS';
      } else {
        this.message = "You don't know JS";
      }
    },
  },
};
</script>
The checked state of the checkbox determines the message displayed when the button is clicked.
The checked state of the checkbox determines the message displayed when the button is clicked.

We set an onClick listener on the button. In this listener, we access the checkbox object using the ref, and use its checked property to determine the message that should be shown to the user when the button is clicked.

How to Push an Object to an Array in JavaScript

To push an object to an array in JavaScript, call the push() method on the array with the object as an argument, i.e., arr.push(obj). The push() method will add the element to the end of the array.

For example:

const arr = [];

const obj = { name: 'Jeff' };

// ๐Ÿ‘‡ Push object to array
arr.push(obj);

// [{ name: 'Jeff' } ]
console.log(arr);

The push() method takes an object and adds it to the end of an array.

Push object to array during initialization

If the variable is newly created just before the object is pushed (like in the previous example), you can simply place the object in between the square brackets ([]) to include it in the array as the variable is initialized:

const obj = { name: 'Jeff' };

// ๐Ÿ‘‡ Push object to array with initialization
const arr = [obj];

console.log(arr);

Push multiple objects to array

The push() method actually accepts a variable number of arguments. They are each added to the end of the array, in the order in which they are passed to push().

For example:

const arr = [];

const obj1 = { name: 'Samantha' };
const obj2 = { name: 'Chris' };
const obj3 = { name: 'Mike' };

arr.push(obj1, obj2, obj3);

// [ { name: 'Samantha' }, { name: 'Chris' }, { name: 'Mike' } ]
console.log(arr);

Push object to array without mutation

The push() method adds an object to the array in place, which means it gets modified. If you don’t want this, you can use the spread syntax (...) to create a copy of the original array, before calling push():

const arr = [{ name: 'Jerry' }];

const newArr = [...arr];

newArr.push({ name: 'Mia' });

// [ { name: 'Jerry' }, { name: 'Mia' } ]
console.log(newArr);

// ๐Ÿ‘‡ Original not modified
console.log(arr); // [ { name: 'Jerry' } ]

Similar to what we did earlier, we can include the object in the square brackets, after the spread syntax, to push the object to the array’s copy as it is initialized:

const arr = [{ name: 'Jerry' }];

// ๐Ÿ‘‡ Push object to array without mutation
const newArr = [...arr, { name: 'Mia' }];

// [ { name: 'Jerry' }, { name: 'Mia' } ]
console.log(newArr);

// Original not modified
console.log(arr); // [ { name: 'Jerry' } ]

While not always necessary, by avoiding mutations we can make our code more readable, predictable, and modular.