Destructuring Objects in ES6

What is destructuring?

Destructuring is a way to extract values from nested arrays and objects.

When you use destructuring, you are taking a JavaScript expression and extracting data from either arrays, objects, maps, and sets into their own variable. It also allows you to extract properties on an object or items from an array in multiples.

Examples

const car = {
  make: 'Subaru',
  model: 'BRZ',
  year: '2018',
  dealership: 'Cochran',
  city: 'Pittsburgh'
};

const make = car.make;
const model = car.model;

In this example, we have some pretty repetitive code where we need to create a variable from some value inside of an object.

Instead of creating multiple variables, we can destructure them to a single, sweet line:

const { make, model } = car;

where we get a variable called make and a variable called model extract them from the car object and putting them into their own variables which are scoped to the parent block, in this case, the window since they aren’t in a nested object.

If I wanted to add another property to the destructured object, I could do something like this:

const { make, model, year } = car;

where we get a top level variable inside our scope.

This is a good use of destructuring, but what if we want to get at data in nested arrays and objects?

Take this data we get from some web API:

const weather = {
  city: 'Pittsburgh',
  state: 'Pennsylvania',
  local: {
    precipitation: {
      snowing: yes,
      raining: no,
    },
    coordinates: {
      lat: '40.4406° N',
      long: '79.9959° W'
    }
  }
};

I just want the latitude and longitude in this case. I could do:

const lat = weather.local.coordinates.lat;
const long = weather.local.cooridinates.long;

but this is not easy to reason about.

Destructuring to the rescue:

const { lat, long } = weather.local.coordinates;
console.log(lat, long);

In this instance we need to destructure weather.local.coordinates because we are destructuring an object a few levels deep.

Other Fun Stuff

You can also rename and destructure variables in ES6.

How?

const snowing = 'no';
const weather = {
  city: 'Pittsburgh',
  state: 'Pennsylvania',
  local: {
    precipitation: {
      snowing: 'yes',
      raining: 'no',
    },
    coordinates: {
      lat: '40.4406° N',
      long: '79.9959° W'
    }
  }
};

Here I already have a snowing variable. I also have a snowing key on the same object. You aren’t able to do this, however, so you will need to rename the variable or the key within the object. In this instance, we can rename the snowing property to snow and the raining property to rain.

const { snowing: snow, raining: rain } = weather.local.precipitaton;

This will assign weather.local.precipitaton to a variable called snow and also to a variable called rain.

JavaScript Template Literals

Photo credit by Hongkiat

Traditionally, strings in JavaScript were limited, especially if you were working in languages like Ruby and Python. In both of those languages string interpolation meant that you could substitute strings and have multiline string concatenation without wonky hacks.

In JavaScript, there wasn’t anything like this until ES6. Now, we have JavaScript Template Literals or template strings.

Syntax

Template strings use back-ticks rather than quotes to denote a string. A template string could look like this:

let hello = `Hello World!`;

String Substitutions

What’s nice about string substitutions is that you can take any JavaScript expression and place it inside a Template Literal and it will be output as part of the string.

The syntax for this:

let name = “Tiffany”;
console.log(`Hey, ${name}!`);

Since string substitutions in Template Literals are JavaScript expressions we can evaluate any type of expression we want in the Template Literal. We can evaluate a mathematical expression such as:

let a = 13;
let b = 20;
console.log(`The Mac first launched ${a+b} years ago. I, for one, welcome my bitten fruit overlord.`);

//  => The Mac launched 33 years ago. I, for one, welcome my bitten fruit overlord.

console.log(`I am old, but not ${2 * (a+b)} yet.`);

//  => I am old, but not 66 yet.
// I know. It doesn’t make sense. Bear with my pitiful examples.

You can even put functions or method calls inside a Template Literal:


// Functions inside expressions function func() { return “I am the result of foo” } console.log(`bar ${func} baz.`); // => I am the result of foo bar baz. //Method calls let hacker = {name: ‘Elliot Anderson’} console.log(`You forgot to quit Vim, ${hacker.name.toUpperCase()}`); // => You forgot to quit Vim, ELLIOT ALDERSON

Multiline Strings

Multiline strings in JavaScript required hacks like the backslash hack and string concatenation like:

let greeting = “Hello “ +
“World”;

Template strings make this a whole lot easier. Add new lines where you need them and the whitespace inside the backticks inside the Template Literal will be included inside the string like so:

console.log(`I'm a string on one line
I’m a string on another line`);

Tagged Templates

Tagged Templates can be used for powerful string transformations. You create a Tagged Template by placing a function name before the template string. Here’s an example of auto escaping an HTML function such that:

html`<p title="${title}">Hello ${name}!</p>`

returns a string with the appropriate variables substituted but with all the unsafe characters replaced.

Nicholas Zakas goes over this in detail in his book Understanding ES6.

Summary

Template Literals or Template Strings are a powerful addition to the JavaScript language that brings it much needed string interpolation and transformation.

Use Cases for the Spread Operator

One of the coolest features of ES6 is the Spread Operator. The syntax looks a bit like:

let a = [4, 5, 6];
let b = [7, …a, 8];

console.log(b);

This will give us:

View post on imgur.com

The spread operator replaces the concat function in ES5:

“use strict“;
var a = [4, 5, 6];
var b = [7].concat(a, [8]);

console.log(b);

This is a great little feature, but what can we do with it?

Some Uses for the Spread Operator

We can do a lot with the spread operator.

Combine Arrays

You can use the spread operator to combine arrays:

let test = () => {
  let arr1 = ['foo', 'bar', 'baz'];
  let arr2 = ['fizz', 'buzz'];
  arr1.push(...arr2); // Will append the contents of arr2 to arr1
};

test(); // Runs function

Copying Arrays

We’ve used Array.prototype.slice to make copies of arrays. Now we can do that with the spread operator.

let arr = [7, 8, 9];
let arr2 = […arr];
arr2.push(10); // Will return a deep copy of the array with 10 appended to the end
//of the values

More At the MDN

You can find more uses for the spread operator at the MDN

ES6 Modules

ES6 modules allows us to have reusable code, in separate files. We do this to eliminate initially massive js files, like app.js in a Node and Express project. Modules allow us to spread code over relevant files.

Take this students.js file

const students = [‘Peter’, ‘Paul’, ‘Mary’];

export const students = [‘Peter’, ‘Paul’, ‘Mary’];

Export allows us to export functions, objects, and primitive values into another files.

In app.js we import those values as modules into the main js file:

import { students } from ‘./students’;

…where ./students represents the file stored in the same directory as app,js.

Importing More than One Value

You can import more than one value from a module. Take students.js:

export const total = 42;

We can import this variable into app.js along with the students array:

import { students, total } from ‘./students’;

Export Data and Functions Between Files

You can export functions between files, such as in this calc.js file:

const add = (x, y) => {
  return x + y;
}

const divide = (x, y) => {
  return x / y;
}

export { add, divide };

To import this module into app.js:

import { add, divide } from ‘./calc’;

Exports are not just limited to primitive data types.

Export Fallbacks with Default

What if we wanted a function to be the main function for our module?

We can add a default keyword to have a fallback:

export { add, divide };
export default multiply;

This will allow the module to fallback on a function if another fails.

Watch for this Pitfall

It may be tempting to do something like this:

export default const add = (x, y) => {
  return x + y;
}

This will result in a TypeError.

Why?

The default keyword creates a variable called default. Adding default and const simultaneously, JavaScript will try to declare two different variables, which is not allowed in most programming languages.

More to Come

ES6 is the standard now and so I am learning it, as quickly as possible. Let me know some of your favorite features of ES6.

Map: Another Higher Order Function

Map is another higher order function that goes through an array and doesn’t discard it but instead transforms/mutates it.

Here, I’d like to get an array of all the names of the animals.

const animals = [
  { name: ‘Catticus Finch’,  species: ‘cat’ },
  { name: ‘Peaches’,         species: ‘fish’ },
  { name: ‘Bobby’,           species: ‘dog’ },
  { name: ‘Lucifer’,         species: ‘cat’ },
  { name: ‘Beatrix’,         species: ‘rabbit’ },
  { name: ‘Cerulean’,        species: ‘fish’ }
];

Here’s how we would accomplish this with a for loop:

var names = [];

for (var i = 0; i < animals.length i+) {
  names.push(animals[i].name); 
}

The function .filter expects a boolean, but .map expects a callback function to return a transformed object it will push into a new array.

To return the names of each of the animals in code:

In ES5:

var names = animals.map(function() {
  return animal.name;
});

In ES6:

const names = animals.map(animal => animal.name);

You can use .map to return a subset of an array. Since it expects a callback to return an object, we can make new objects.

In ES5

var names = animals.map(function(animal) {
  return animal.name + ‘ is a ‘ + animal.species;
});

In ES6

const names = animals.map(animal => animal.name + ‘is a ‘ + animal.species);

Easier Array Manipulation with Higher Order Functions

.map() and .filter() are just a couple of higher order functions you can use to manipulate and iterate over arrays.

You can check out this link for further reading.

Functional Programming in JavaScript? Yes Please.

One of the hot topics right now in the web development world is functional programming in the language of the web, JavaScript.

Functional programming encompasses a whole host of mathematical properties and phenomena that is beyond this post, but what I am going to address here is how to write a a few functions with nominal functional programming.

This is going to be a series. I am currently researching these topics as I go along and what I find excites me. I will be digging into these topics, each array method bit by bit. You can find some more of this on Steve Smith’s blog Funky Javascript.

Important Concept: Higher Order Functions

One of the best and worst parts about JavaScript is that you can pass functions into other functions. This can lead to beautifully expressive code and sometimes bugs.

Why can we do this? Because, like in most functional programming languages 1, functions are values just like any other value in JavaScript.

Take this code:

// Named function or
// function declaration
function double(x) {
  return x * 2;
}

// Anonymous function or
// Function expression
let double = function(x) {
  return x * 2;
}

let cat = double;
// Function call
cat(60);

// returns 120, obviously

Here we have named function called double. It takes an argument, x and when you call it, it returns whatever the value of x is that you specify in the function call and returns it.

What’s different about JavaScript is that you can pass it into a variable and call the function from that variable. This is because, well, functions are values.

Higher order functions are good for composition to take smaller functions and make them into bigger functions. More on this in a minute.

Enter .filter()

The .filter() function is an array function that takes a callback that it uses to create a new filtered version of an array.

Take this array of objects:

let animals = [
  { name: ‘Catticus Finch’, species: ‘cat’ },
  { name: ‘Peaches’ species: ‘fish’ },
  { name: ‘Bobby’, species: ‘dog’ },
  { name: ‘Lucifer’, species: ‘cat’ },
  { name: ‘Beatrix’, species: ‘rabbit’ },
  { name: ‘Cerulean’ species: ‘fish’ }
];

Say I wanted to filter out all this cats in this array. We could use the trusty for loop:

let cats = []

for (let i = 0; i < animals.length; i++) {
  if (animals[i].species === ‘cat’) {
    cats.push(animals[i]);
  }
}

We are essentially just looping through the array and for every cat the for loop finds, it pushes it into the empty cat array.

Now, we can filter.

Filter accepts a callback and loops through each item in the array and passes it back to the callback function. .filter() expects a boolean and then returns the filtered array.

In ES5:

let cats = animals.filter(function(animal) {
  return animal.species === ‘cat’;
});

In ES6

let cats = animals.filter(animal => animal.species === ‘cat’);

Here, if the value of the species property in the animals array is a cat it will return the names of those cats in a filtered array.

We could also write an anonymous function and add a filter function inside of it, much like this:

let isCat = function(animal){
  return animal.species === ‘cats’;
});

let cats = animals.filter(isCat);

How Cool is This?

Writing small functions allows composition which we can reuse. In the for loop, we are pushing cats into the array but filter handles this natively.

Filter and the callback are composed as they are meshed into each other. Not only is it syntactically pleasing, but it is less lines of code which is always a good thing.

Next Up

Next I want to tackle the .map() function and get back to my Chrome DevTools series.


  1. Though JavaScript isn’t a purely functional programming language. 

Mission DRY: Accomplished

When working with multiple levels of conditionals, it helps to DRY things up a bit: not repeating yourself can give performance gains as well as make your code more readable and elegant.

Here is one of the monstrosities I had before:

if (currentIcon === "clear-day")   {
  $("body").css("background-image", "url(https://i.imgur.com/voece1h.jpg)");
  }   else if (currentIcon === "partly-cloudy-night")   {
  $("body").css("background-image", "url(https://i.imgur.com/r8haFIj.jpg)");
  }   else if (currentIcon === "clear-night")   {
  $("body").css("background-image", "url(https://i.imgur.com/K6Bazrl.jpg)");
  }   else if (currentIcon === "partly-cloudy-day").  {
  $("body").css("background-image", "url(https://i.imgur.com/dUS9u9b.jpg)");
  }   else if (currentIcon === "cloudy")   {
  $("body").css("background-image", "url(https://i.imgur.com/Kx3ku27.jpg)");
  }   else if (currentIcon === "rain")   {
  $("body").css("background-image", "url(https://i.imgur.com/g4afvja.jpg)");
  }   else if (currentIcon === sleet)   {
  $("body").css("background-image", "url(https://i.imgur.com/pjq3VPO.jpg)");
  }   else if (currentIcon === snow)   {
  $("body").css("background-image", "url(https://i.imgur.com/vH9cyKD.jpg)");
  }   else if (currentIcon === wind)   {
  $("body").css("background-image", "url(https://i.imgur.com/ZtSl66b.jpg)");
  }   else if (currentIcon === fog)   {
  $("body").css("background-image", "url(https://i.imgur.com/5z0CXkZ.jpg)");
}

Really gross, right?

Consulting LinkedIn and Slack proved to be fruitful.

Changing if/else Chains Into Map Objects

A hash map is an object that you can iterate over like an array. The definition of a Map object can be found on the MDN.

Adam Recvlohe, a fellow freeCodeCamp Camper on LinkedIn recommended I use a Map for changing the background of my freeCodeCamp Weather App dynamically. He showed me some code and I eventually settled on this:

const iconMap = {
  "clear-day": "url(https://s3.us-east-2.amazonaws.com/weatherappfcc/sunny.jpg)",
  "partly-cloudy-night": "url(https://s3.us-east-2.amazonaws.com/weatherappfcc/fineas-anton-136459+copy.jpg)",
  "clear-night": "url(https://s3.us-east-2.amazonaws.com/weatherappfcc/sam-mcjunkin-38078.jpg)",
  "partly-cloudy-day": "url(https://s3.us-east-2.amazonaws.com/weatherappfcc/jeff-nafura-294909.jpg)",
 "cloudy": "url(https://s3.us-east-2.amazonaws.com/weatherappfcc/jonatan-pie-260835.jpg)",
 "rain": "url(https://s3.us-east-2.amazonaws.com/weatherappfcc/3opt\_rain.jpeg)",
 "sleet": "url(https://s3.us-east-2.amazonaws.com/weatherappfcc/jonatan-pie-190398.jpg)",
 "snow": "url(https://s3.us-east-2.amazonaws.com/weatherappfcc/snow.jpg)",
 "wind": "url(https://s3.us-east-2.amazonaws.com/weatherappfcc/jon-flobrant-2845.jpg)",
 "fog": "url(https://s3.us-east-2.amazonaws.com/weatherappfcc/elaine-li-416.jpg)"
};

(function() {
  $("body").css("background-image", iconMap[currentIcon]);
})();

Here, we take a Map object and use an anonymous function calls the .css jQuery method on the body which will change the background image by injecting that css into the body. Also as an argument to the css method is an iteration over the iconMap Map object that maps each image to the currently displayed Skycon.

Next: Cleaning Up The if/else Mess of an Icon Display

Up above you probably observed my conditional hell. It was the same for the icons where I called the jQuery show()/hide() methods in if/else statements for every. Icon. Pure insanity.

I went to the Code Newbie Slack and asked Joseph Rex for help as he has been guiding me through a few of the Express and other JavaScript problems I have been having. After some bugs and error handling we came up with a nifty ES6 solution that is much cleaner, using Template Literals to clean up the constant calls to each icon.

// Write a function that takes two parameters
let iconDisplay = (iconName, current) => {
   //Assign a template literal to a constant that will
//represent each icon
   const jqObj = $(`#${iconName}`);
   // Use the ternary operator to determine with the //iconName is the current icon being shown for the condition
//and based on that, show or hide the appropriate icon
   iconName === current ? jqObj.show() : jqObj.hide();
};

 // call the function and compare it to the Skycon for each 
 // Weather condition.
 iconDisplay("clear-day", currentIcon);
 iconDisplay("clear-night", currentIcon);
 iconDisplay("partly-cloudy-day", currentIcon);
 iconDisplay("partly-cloudy-night", currentIcon);
 iconDisplay("cloudy", currentIcon);
 iconDisplay("fog", currentIcon);
 iconDisplay("rain", currentIcon);
 iconDisplay("sleet", currentIcon);
 iconDisplay("snow", currentIcon);
 iconDisplay("wind", currentIcon);

Pretty cool.

Learning Express with The Web Developer Bootcamp

Pretty soon I’ll be diving deep into how much I am learning about Express with The Web Developer Bootcamp. To get a sense of where I was a couple days ago, read this.

CRUD: My New App, Check Yo Self

I have taken a bit of a break from the coding/learning thing as I suffer from a bit of depression every now and again, outside of the usual. It’s a woman’s thing, as they say.

So while I was a bit down and cantankerous I took a break to tweak a few of my sites and read some documentation. After the bout of depression subsided, I dove into SQL.

Create, Read, Update, Delete: CRUD

I asked around in the Code Newbie Slack and asked my buddy Alex if I could use localStorage to store the markdown documents.

Let me backtrack.

When I was designing the app, I got the idea of having the markdown documents collect on the side of the app, sort of like the design template I was using. I knew I’d need to store those documents and really didn’t want to dive into databases.

I thought about using localStorage. Alex told me that localStorage has a capacity limit. I really don’t know how many texts someone would store and come back to, and while text files are minuscule, I don’t want to risk it.

I could go the I Need a Resume route and use setSessionCookie which would require less overhead. But if the user clears their cookies, all their texts would be wiped out.

I still plan to use setSessionCookie but I am not sure how I am going to work it in with storing the texts in the database.

CRUD is a SQL thing. 1.

ORMs and JavaScript May Save Me, Big Time

While learning SQL at Treehouse, Andrew Chalkley, the teacher, explained ORMs, or Object Relational Mapping software that helps you interface with a database in different languages. For instance, ActiveRecord for Ruby and Hibernate for Java.I was having a hard time understanding how to store the texts the users input, store the texts, and retrieve the texts up until that point in the course. Everything we did in the course was hard coded and I definitely understood I could not do that. ORMs to the rescue. Searched for an ORM for JavaScript and there are many, either through npm or other means, there are plenty. Still researching. Since I am using Postgres on Heroku, it needs to play nice with it and I found one called sequelize.js that looks like it will do the trick:


var Sequelize = require('sequelize');
var sequelize = new Sequelize('database', 'username', 'password');

var User = sequelize.define('user', {
  username: Sequelize.STRING,
  birthday: Sequelize.DATE
});

sequelize.sync().then(function() {
  return User.create({
    username: 'janedoe',
    birthday: new Date(1980, 6, 20)
  });
}).then(function(jane) {
  console.log(jane.get({
    plain: true
  }));
});

This snippet seems quite easy to grasp and will make interfacing with Heroku’s Postgres addon even easier. 2.

Coding Again

I plan on scanning more docs and getting the HTML up and going. I felt overwhelmed with the amount of stuff I needed to code. This is one area that hinders me still: not breaking big projects up into little pieces. I decided I have been at this enough that I should actually take Russ’s 3 and break that shit down. I fired up Drafts app on my iPhone and wrote down every task I needed and wanted to complete. Then I shifted those over to OmniFocus and Taskpaper. There are more tasks to add but I feel a sense of relief knowing that the ideas are down, and that I should work on one small bit of code at a time.

Thoughts?

I never know how to end these things. Let me know what you’re hacking on in the comments. Or not. It’s all good. ????


  1. Create: INSERT INTO, Read:, SELECT * FROM, Update: UPDATE SET, and, Delete: DELETE FROM. So that’s why they call database apps that are simple CRUD apps, which I understand finally. 
  2. Check out sequelize.js 
  3. Code Newbie field general, 1000XP 

Concise, Modular JavaScript

Working with JavaScript again at Treehouse, I went over the Arrow Syntax again1.

Before it really wasn’t making much sense. I mean, I thought I had it down, but really, it was too fast and too complicated for me at the time. I wanted to learn ES2015 and write, clean, concise, modular javascript.

So What’s Different?

I actually rewatched the videos with Andrew Chalkley this time2.

Take a look at this code:

Here we are taking no arguments passed to the function sayName()3. With arrow functions, we can write modular, clean code4. We can get rid of the function keyword and replace it with =>. Pretty nifty, eh?

Single Argument Functions

Take a look at this code:

When we have a single argument passed to a function, much like the no arguments function, we replace the function keyword with an =>. But we can also remove the curly brackets, the parens, and the return statement.5

This is getting pretty awesome.

Multiple Argument Functions

Take another gander at this gist:

Here, we can do pretty much the same thing as in the single argument function, only we need to keep the parens. Still, you can get rid of the curly braces, and the one line of code in the block.

It’s Really All The Same

Check out this gist:

It’s just a cleaner, more modular way to write code. I hear you can write modular JavaScript with Promises but I am not there yet.

Enrolled in Coursera Course

I am doing their Java Data Structures and Algorithms course. They waived the tuition and so I am starting soon. The capstone is what I am really looking forward to. I need to put in the work: 4-6 hours a week. Not too bad.

Thoughts?

Have anything to add? Leave me a comment. 🙂


  1. I called them lambda functions in this post. I don’t think they’re the same, however. 
  2. I actually rewatched them a couple times and downloaded the completed workspace. 
  3. Learning ES2015 and so we are now using const
  4. Much to the rejoicing of Uncle Bob Martin
  5. As stated in the comment, you can only do this when there is one line of code in the code block and one argument. 

Bonfire Tears (Free Code Camp Edition)

\"Crying\"

“Laughter and tears are both responses to frustration and exhaustion. I myself prefer to laugh, since there is less cleaning do to do afterward.” ― Kurt Vonnegut

There comes a point in every new programmers life when they hit a barrier, a wall, a threshold of understanding or non-understanding of the material at hand.

I hit that threshold yesterday.

And the day before it. It was a solution so simple; I had the right idea several times. I got explained to and encouraged, and guided and it was like their words were bouncing off my skull instead of being absorbed into my grey matter. The question was:

Check if a string (first argument) ends with the given target string (second argument).

Remember to use Read-Search-Ask if you get stuck. Write your own code.

Here are some helpful links:

String.substr()

The given code:

function end(str, target) {
 // "Never give up and good luck will find you."
 // -- Falcor
 return str;
}




end("Bastian", "n");

What the Hell Substrings?

\"headdesk\"

You’ve done it before and you can do it now. See the positive possibilities. Redirect the substantial energy of your frustration and turn it into positive, effective, unstoppable determination. –Ralph Marston

I knew that, since we had lengths of different strings. The tests proved that. So I kept hardcoding for one particular string. I couldn’t get past that. How do I code this thing for different string lengths? How do you get the length of a string? .length. Right? YES. But how. Where do I put the .length? I had this code:

function end(str, target) {
 //"Never give up and good luck will find you."
 // -- Falcor




//dees [8:42 PM]
//\'abcdefghijklmn\'.substr(0, 3) // \'abc\'
//"grab 3 characters starting with the character at address number 0"
​
 var isEqual = str.substr(6, 1) === target.substr(0, 1);
 return isEqual;




}
​
end("Bastian", "n");

I found out in Free Code Camp’s Gitter chat that you can get to the end of a string with a negative number; no need to keep popping off all those letters before the “n” on Bastian. But I continued to hard code for “Bastian” and “n”. I needed a broader approach.

I tried:

function end(str, target) {

​
 var isEqual = str.substr(-1) === target.substr(-1);
 return isEqual;




}
​
end("Bastian", "n");

But I wasn’t really making any progress. All but one of the tests were passing, and I wasn’t really utilizing .length to have a basic variance of string lengths. So I did this:

function end(str, target) {

 var n = target.length;
 var z = str.length;
 var isEqual = str.substr(-1) === target.substr(-1);
 return isEqual;

}
​
end("Bastian", "n");

Same result. I knew I needed to have .length; up there. But where to go after that?

Aha!

\"Aha\"

Finally, I had to be guided to the answer. The woman was in Britain and I am pretty sure I was keeping her awake. So we came up with this solution:

function end(str, target) {
 // "Never give up and good luck will find you."
 // -- Falcor

 var length = target.length;
 var isEqual = target === str.substr(-length);
 return isEqual;
}

end("Bastian", "n");

var length = target.length; gets the length of any target string and assigns it to the length variable.
var isEqual = target === str.substr(-length); compares the target string with the original string, subtracting the last characters of the length variable, starting with the end of the string.

I hope I explained that right. I understand it. It takes a bit to look at and understand but when we came to that solution, I felt like a complete idiot.

I cried. I literally did. Part of that is just me already being emotional. The other part is me not wanting to put my fist through my MacBook Pro screen. Strings are characters. Not words. And I was totally getting stuck on that.

Bonfire tears indeed.