JavaScript DeepClone function created by ChatGPT and it works

One thing I hate dealing with is cloning JavaScript Objects. Well, deep cloning JavaScript Objects. So I decided to see if AI could write me a quick function.

And it did.

I asked ChatGPT “Can you write me a JavaScript function which will deep clone a JavaScript Object?”

And this was it’s response:

Certainly! You can create a deep clone function in JavaScript using recursion to clone nested objects and arrays. Here’s a sample function to deep clone a JavaScript object:

function deepClone(obj) {
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }

  if (Array.isArray(obj)) {
    const cloneArr = [];
    for (let i = 0; i < obj.length; i++) {
      cloneArr[i] = deepClone(obj[i]);
    }
    return cloneArr;
  }

  const cloneObj = {};
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      cloneObj[key] = deepClone(obj[key]);
    }
  }

  return cloneObj;
}

You can use this deepClone function to create a deep copy of a JavaScript object. Here’s an example of how to use it:

const originalObj = {
  name: 'John',
  age: 30,
  address: {
    street: '123 Main St',
    city: 'Exampleville',
  },
};

const clonedObj = deepClone(originalObj);

console.log(clonedObj);

The clonedObj will be a deep copy of the originalObj, so you can modify it without affecting the original object.

How to pad a string in JavaScript

Sometimes you need your string to be a set length, like maybe you have numbers that all need to be 10 characters long regardless of the number value. Or maybe you have a credit card number and want to just show the last 4 digits while everything else is replaced with an asterisk (*). Regardless of the reason, JavaScript now has built in methods to add the padded characters to either the start or the end of your string. Let’s begin with the padding at the start to get the idea going.

Say you have an invoice system that needs it’s invoice numbers to be 10 characters, but you are only up to invoice number 4532. You’ll want to have six zeros prepended to the invoice number for display. To do this, we will use JavaScript’s padStart() method. This method takes two parameters: targetLength & padString. targetLength is how long the string will be once the desired number of characters have been added. padString is the character that will be used for padding; if none is supplied, JavaScript will use " " (U+0020 'SPACE').

Using the invoice example above, your code would look like this:

let invoiceNumber = "4532"
invoiceNumber.padStart(10, '0')
// Output: "0000004532"

The padEnd() method works the same way but appends the padding character to the end of the string. So, our example would look like this instead:

let invoiceNumber = "4532"
invoiceNumber.padEnd(10, '0')
// Output: "4532000000"

More Information:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd

How to subtract or add days from a Date in JavaScript?

If you have a date in JavaScript and need to subtract (or add) a number of days to that date, you will want to use JavaScript’s built in setDate() method. This will set the day of the month for a given date.

NOTE:
setDate() is based on local time. If you want to work with UTC time then use setUTCDate()

So, if you wanted to set the day of the month to be the 15th of the current month you would start with today’s date and change the date like so:

var d = new Date();
d.setDate(15);
// Sun Aug 15 2021 16:49:25 GMT-0500 (Central Daylight Time)

Using this approach combined with the getDate() method (which returns the current month’s date for a given date), you can substract or add days. If you want to get the date which is Today – 5 days then you could use:

var d = new Date();
d.setDate(d.getDate()-5);
// Tue Aug 10 2021 16:56:31 GMT-0500 (Central Daylight Time)

More Information:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setDate

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getDate

How to get the last element in a JavaScript Array

Let’s say you have an array of numbers (but it could be an array of anything really):

const myNumbers = [1,2,3,4,5]

You want the last number in the array but don’t care how many elements are in the array. The simplest way to get the last number in the array is to get the element who’s position is the same as the length of the array minus 1. The minus 1 is because arrays are zero based, so the first element is accessed like so:

const selectedNumber = myNumbers[0]

Therefore, the easiest way to get the last element from an array without knowing how many elements are in the array is like this:

const lastNumber = myNumbers[myNumbers.length - 1]

Vue.JS — Error when clicking link, but works on second click

Had a not so obvious issue pop up recently in a Vue.JS app I’ve been working on for a while now. I have a table of members and if you click the member name, you get redirected to their profile page. There is a click event on the name link so it will store the profile id then use the router to push the new route. The issue is that when you click the link, you get the following error:

Navigation console error

BUT if you click the link a second time you get redirected to the profile page as expected. This error is basically saying you can’t navigate to the same page you are on. Which is not what I was trying to do. So I was confused.

Turns out everything was working properly in my code I just didn’t account for it all. Here is my original link:

<a href="#" @click="individualStoreKeyAndRedirect(data)">{{ data.value }}</a>

The trouble is the href=”#” is firing before my @click event fires. So, Vue’s router thinks I’m trying to go to the same page. To make the behavior what I wanted, I had to prevent that from firing and just fire my @click event.

Thankfully, Vue makes it pretty easy. Just add .prevent to your @click event. My new link looks like this:

<a href="#" @click.prevent="individualStoreKeyAndRedirect(data)">{{ data.value }}</a>

And now everything works the way I wanted and no console error!

JavaScript — Get the Currently Focused Element

In JavaScript, the currently active element is said to have Focus, which means it’s the element being acted upon. Like a form field in which you are typing is said to have Focus.

You can get the currently focused element with a simple reference on the Dom:

var currentElement = document.activeElement

This will return the element which has focus, or null if there is no focused element. It will let you have access to the whole element. You can get to any properties on that element like the Id or Name. The CodePen below is a simple example of using the document.activeElement

Example

See the Pen Get Focused Element by Chris (@cgreenws) on CodePen.

For more information:
https://www.w3schools.com/jsref/prop_document_activeelement.asp
or
https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot/activeElement

JavaScript — How to use the Set object

JavaScript has an object called Set which will store any type with unique values — this can be a primitive value type (e.g. string, number, boolean, null, undefined, symbol) or even an object reference.

//create a new Set
var setA = new Set();
//use .add() to add types to the set
setA.add(6); // Set is [6]
setA.add(9); // Set is [6,9]

//or create a Set by passing it an iterable object
var setA = new Set([6,9]); // Set is [6,9]

Because a value in a Set may only occur once, it will eliminate duplicates when you add them.

//Eliminates duplicate values on creation
var setB = new Set([6,7,8,9,6,7]); // Set is [6,7,8,9]

//Doesn't add new values if they already exist in the set
var setB = new Set();
setB.add(6)// Set is [6]
setB.add(7)// Set is [6,7]
setB.add(8)// Set is [6,7,8]
setB.add(6)// Set is [6,7,8]
setB.add(9)// Set is [6,7,8,9]
setB.add(7)// Set is [6,7,8,9]

Use the .has() method to check if a value is in the set. It will return a boolean of True or False depending on if it finds the value.

var setA = new Set([6,9,3,5,8]);
setA.has(5); // true
setA.has(2); // false

The .delete() method will remove a value from the set. It will return a boolean value if it found the value in the set.

var setA = new Set([6,9,3,5,8]);
setA.has(5); // true
setA.delete(5); // returns true
setA.has(5); // false -- Set is now [6,9,3,8]
setA.delete(5); // returns false

You can also remove ALL the values in the set with the .clear() method.

var setA = new Set([6,9,3,5,8]);
setA.has(5); // true

A Set does not have a Length property but it does has a Size which will tell you how many values are stored in the Set.

var setA = new Set([6,9,3,5,8]);
setA.size; // return 5
setA.length; // returns undefined

To keep the Set similar to the Map object, values are stored as a key/value pair where the key is the same as the value. You can retrieve all the values in a Set using the .entries() method. This will return an Iterator of all entries in a format of [value, value].

var setA = new Set([6,9,3,5,8]);
var myEntries = setA.entries();

You can also just get the keys or values for a Set using the .keys() or .values() methods, respectively. Both return a new Iterator object. Since the value is used as the key in a Set, both methods ultimately return the same result.

var setA = new Set([6,9,3,5,8]);

var setKeys = setA.keys();
// or
var setValues = setA.values();

Because a Set is an iterable object, you can use the .forEach() method to loop over the values in a Set. You can pass a call back function in as a parameter which will get called once for each value in the set. It also has an option argument which can be passed that will be used for the this value for each callback.

var setA = new Set([6,9,3,5,8]);

setA.forEach(function writeValue(value) {
     console.log(value);
});

// 6
// 9
// 3
// 5
// 8

// example passing 'a' as the thisArg to the forEach
setA.forEach(function writeValue(value) {
     console.log(value + '---'+ this );
}, 'a');

// 6---a
// 9---a
// 3---a
// 5---a
// 8---a

If you just want to iterate over the values in a Set, you also have the option of using a For loop.

var setA = new Set([6,9,3,5,8]);

for (let item of setA) {
     console.log(item);
}
// or 
for (let item of setA.values()) {
     console.log(item);
}

// both output
// 6
// 9
// 3
// 5
// 8

You can easily convert from a Set to an array using Array.from() method.

var setA = new Set([6,9,3,5,8]);

var array1 = Array.from(setA); // [6, 9, 3, 5, 8]

//you can also use the Spread Syntax to create the Array of Values
var array2 = [...setA]; // [6, 9, 3, 5, 8]

One neat trick you can use Set for is to de-dupe an Array.

var array1 = [6,9,3,5,8,9,4,2,1,2,2]

var setB = new Set(array1);

var array2 = [...setB] //[6, 9, 3, 5, 8, 4, 2, 1]

// or you can simplify things like so
var array3 = [...new Set([6,9,3,5,8,9,4,2,1,2,2])]; 
//[6, 9, 3, 5, 8, 4, 2, 1]

Another is to use Set as a way to break a string apart to it’s individual unique letters.

var myString = 'Hello';

var charSet = new Set(myString); // ["H", "e", "l", "o"]
charSet.size; //4

//just keep in mind that case sensitivity counts
var myString2 = 'HeLlo';

var charSet2 = new Set(myString2); // ["H", "e", "L", "l", "o"]
charSet2.size; //5

There are a couple things to keep in mind. A set can only contain unique values. When you interate over a Set object, it returns the values in insertion order (how they go in is how they come out).

Objects can be a bit confusing at first compared to primitive types. For instance:

var obj = {'a': 1, 'b':2}
var obj2 = {'a': 1, 'b':2}
var mySet = [{'a': 1, 'b':2}, obj, obj2]

// mySet now contains
// [{'a': 1, 'b':2}, {'a': 1, 'b':2}, {'a': 1, 'b':2}]

JavaScript — Loop Over an Array with forEach() Method

You can use the forEach() method to loop over an array and execute a function on each element of the array.

var pets = ['dog', 'cat', 'monkey'];

pets.forEach(function(element) {
  console.log(element);
});

// expected output: "dog"
// expected output: "cat"
// expected output: "monkey"

For more information:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

Electron Error: Not allowed to load local resource

I’ve recently begun playing with Electron (the library that lets you build cross-platform desktop apps with web technologies). And not long into trying to hook up my default HTML page I received this error:

Not allowed to load local resource

I was certain I’d typed the line to load the URL just like the tutorial suggested. I searched around and was having trouble finding out why my app wasn’t working. Finally, in a reply buried in the comments was the answer. I was using single quotes and what I needed was the back tick for my value passed.

I had this

mainWindow.loadURL('file://${__dirname}/countdown.html');

But needed this

mainWindow.loadURL(`file://${__dirname}/countdown.html`);

It’s an incredibly easy thing to not notice, but because I was dynamically swapping out the ${__dirname} variable, I had to use the back ticks (`) and not the single quote (‘).

Hopefully that will help other Electron beginners experiencing the same issue.