Undefined: The Third Boolean Value

I wanted to implement a notification message in one of my projects, similar to what you’d see in Google Docs while a document is saving. In other words, a message shows up indicating that the document is saving every time a change is made. Then, once the changes are saved, the message becomes: “All changes saved in Drive.”

Let’s take a look at how we might do that using a boolean value, but actually covering three possible states. This definitely isn’t the only way to do this, and frankly, I’m not even sure if it’s the best way. Either way, it worked for me.

Here’s an example of that “Saving…” state:

Screenshot of the Google Docs header with a message that says the document is saving.
The “Saving” notification displays any time a change is made to the document.

…and the “Saved” state:

Screenshot of the the message reading All Changes Saved after saving has completed.
The “Saved” notification displays once a change or set of changes has completed.

Using a Boolean value for to define the state was my immediate reaction. I could have a variable called isSaving and use it to render a conditional string in my template, like so:

let isSaving;

…and in the template:

<span>{{ isSaving ? ‘Saving...’ : ‘All changes saved’ }}</span>

Now, whenever we start saving, we set the value to true and then set it to false whenever no save is in progress. Simple, right?

There is a problem here, though, and it’s a bit of a UX issue. The default message is rendered as “All changes saved.” When the user initially lands on the page, there is no saving taking place and we get the “Saved” message even though no save ever happened. I would prefer showing nothing until the first change triggers the first “Saving” message.

This calls for a third state in our variable: isSaving. Now the question becomes: do we change the value to a string variable as one of the three states? We could do that, but what if we could get the third state in our current boolean variable itself?

isSaving can take two values: true or false. But what is the value directly after we have declared it in the statement: let isSaving;? It’s undefined because the value of any variable is undefined when it’s declared, unless something is assigned to it. Great! We can use that initial undefined value to our advantage… but, this will require a slight change in how we write our condition in the template.

The ternary operator we are using evaluates to the second expression for anything that can’t be converted to true. The values undefined and false both are not true and, hence, resolve as false for the ternary operator. Even an if/else statement would work a similar way because else is evaluated for anything that isn’t true. But we want to differentiate between undefined and false . This is fixable by explicitly checking for false value, too, like so:

<span>
{{ isSaving === true ? ‘Saving...’ : (isSaving === false ? ‘All changes saved’: ‘’) }}
</span>

We are now strictly checking for true and false values. This made our ternary operator a little nested and difficult to read. If our template supports if/else statements, then we can refactor the template like this:

<span>
{% if isSaving === true %} Saving...
{% elseif isSaving === false %} All changes saved
{% endif %}
</span>

Aha! Nothing renders when the variable is neither true nor false — exactly what we want!

The post Undefined: The Third Boolean Value appeared first on CSS-Tricks.

An Illustrated (and Musical) Guide to Map, Reduce, and Filter Array Methods

Map, reduce, and filter are three very useful array methods in JavaScript that give developers a ton of power in a short amount of space. Let’s jump right into how you can leverage (and remember how to use!) these super handy methods.

Array.map()

Array.map() updates each individual value in a given array based on a provided transformation and returns a new array of the same size. It accepts a callback function as an argument, which it uses to apply the transform.

let newArray = oldArray.map((value, index, array) => { ...
});

A mnemonic to remember this is MAP: Morph Array Piece-by-Piece.

Instead of a for-each loop to go through and apply this transformation to each value, you can use a map. This works when you want to preserve each value, but update it. We’re not potentially eliminating any values (like we would with a filter), or calculating a new output (like we would use reduce for). A map lets you morph an array piece-by-piece. Let’s take a look at an example:

[1, 4, 6, 14, 32, 78].map(val => val * 10)
// the result is: [10, 40, 60, 140, 320, 780]

In the above example, we take an initial array ([1, 4, 6, 14, 32, 78]) and map each value in it to be that value times ten (val * 10). The result is a new array with each value of the original array transformed by the equation: [10, 40, 60, 140, 320, 780].

An illustration of the code examples covered in this section.

Array.filter()

Array.filter() is a very handy shortcut when we have an array of values and want to filter those values into another array, where each value in the new array is a value that passes a specific test.

This works like a search filter. We’re filtering out values that pass the parameters we provide.

For example, if we have an array of numeric values, and want to filter them to just the values that are larger than 10, we could write:

[1, 4, 6, 14, 32, 78].filter(val => val > 10)
// the result is: [14, 32, 78]

If we were to use a map method on this array, such as in the example above, we would return an array of the same length as the original with val > 10 being the “transform,” or a test in this case. We transform each of the original values to their answer if they are greater than 10. It would look like this:

[1, 4, 6, 14, 32, 78].map(val => val > 10)
// the result is: [false, false, false, true, true, true]

A filter, however, returns only the true values. So the result is smaller than the original array or the same size if all values pass a specific test.

Think about filter like a strainer-type-of-filter. Some of the mix will pass through into the result, but some will be left behind and discarded.

An illustration of a funnel with numbers going in the top and a few coming out of the bottom next to a handwritten version of the code covered in this section.

Say we have a (very small) class of four dogs in obedience school. All of the dogs had challenges throughout obedience school and took a graded final exam. We’ll represent the doggies as an array of objects, i.e.:

const students = [ { name: "Boops", finalGrade: 80 }, { name: "Kitten", finalGrade: 45 }, { name: "Taco", finalGrade: 100 }, { name: "Lucy", finalGrade: 60 }
]

If the dogs get a score higher than 70 on their final test, they get a fancy certificate; and if they don’t, they’ll need to take the course again. In order to know how many certificates to print, we need to write a method that will return the dogs with passing grades. Instead of writing out a loop to test each object in the array, we can shorten our code with filter!

const passingDogs = students.filter((student) => { return student.finalGrade >= 70
}) /*
passingDogs = [ { name: "Boops", finalGrade: 80 }, { name: "Taco", finalGrade: 100 }
]
*/

As you can see, Boops and Taco are good dogs (actually, all dogs are good dogs), so Boops and Taco are getting certificates of achievement for passing the course! We can write this in a single line of code with our lovely implicit returns and then remove the parenthesis from our arrow function since we have single argument:

const passingDogs = students.filter(student => student.finalGrade >= 70) /*
passingDogs = [ { name: "Boops", finalGrade: 80 }, { name: "Taco", finalGrade: 100 }
]
*/

Array.reduce()

The reduce() method takes the input values of an array and returns a single value. This one is really interesting. Reduce accepts a callback function which consists of an accumulator (a value that accumulates each piece of the array, growing like a snowball), the value itself, and the index. It also takes a starting value as a second argument:

let finalVal = oldArray.reduce((accumulator, currentValue, currentIndex, array) => { ...
}), initalValue;
An illustration of a saucepan cooking ingredients next to handwritten code from the examples covered in this section.

Let’s set up a cook function and a list of ingredients:

// our list of ingredients in an array
const ingredients = ['wine', 'tomato', 'onion', 'mushroom'] // a cooking function
const cook = (ingredient) => { return `cooked ${ingredient}`
}

If we want to reduce the items into a sauce (pun absolutely intended), we’ll reduce them with reduce()!

const wineReduction = ingredients.reduce((sauce, item) => { return sauce += cook(item) + ', ' }, '') // wineReduction = "cooked wine, cooked tomato, cooked onion, cooked mushroom, "

That initial value ('' in our case) is important because if we don’t have it, we don’t cook the first item. It makes our output a little wonky, so it’s definitely something to watch out for. Here’s what I mean:

const wineReduction = ingredients.reduce((sauce, item) => { return sauce += cook(item) + ', ' }) // wineReduction = "winecooked tomato, cooked onion, cooked mushroom, "

Finally, to make sure we don’t have any excess spaces at the end of our new string, we can pass in the index and the array to apply our transformation:

const wineReduction = ingredients.reduce((sauce, item, index, array) => { sauce += cook(item) if (index < array.length - 1) { sauce += ', ' } return sauce }, '') // wineReduction = "cooked wine, cooked tomato, cooked onion, cooked mushroom"

Now we can write this even more concisely (in a single line!) using ternary operators, string templates, and implicit returns:

const wineReduction = ingredients.reduce((sauce, item, index, array) => { return (index < array.length - 1) ? sauce += `${cook(item)}, ` : sauce += `${cook(item)}`
}, '') // wineReduction = "cooked wine, cooked tomato, cooked onion, cooked mushroom"

A little way to remember this is to recall how you make sauce: you reduce a few ingredients down to a single item.

Sing it with me!

I wanted to end this blog post with a song, so I wrote a little diddy about array methods that might just help you to remember them:

The post An Illustrated (and Musical) Guide to Map, Reduce, and Filter Array Methods appeared first on CSS-Tricks.

Understanding Event Emitters

Consider, a DOM Event:

const button = document.querySelector("button"); button.addEventListener("click", (event) => /* do something with the event */)

We added a listener to a button click. We’ve subscribed to an event being emitted and we fire a callback when it does. Every time we click that button, that event is emitted and our callback fires with the event.

There may be times you want to fire a custom event when you’re working in an existing codebase. Not specifically a DOM event like clicking a button, but let’s say you want to emit an event based on some other trigger and have an event respond. We need a custom event emitter to do that.

An event emitter is a pattern that listens to a named event, fires a callback, then emits that event with a value. Sometimes this is referred to as a “pub/sub” model, or listener. It’s referring to the same thing.

In JavaScript, an implementation of it might work like this:

let n = 0;
const event = new EventEmitter(); event.subscribe("THUNDER_ON_THE_MOUNTAIN", value => (n = value)); event.emit("THUNDER_ON_THE_MOUNTAIN", 18); // n: 18 event.emit("THUNDER_ON_THE_MOUNTAIN", 5); // n: 5

In this example, we’ve subscribed to an event called “THUNDER_ON_THE_MOUNTAIN” and when that event is emitted our callback value => (n = value) will be fired. To emit that event, we call emit().

This is useful when working with async code and a value needs to be updated somewhere that isn’t co-located with the current module.

A really macro-level example of this is React Redux. Redux needs a way to externally share that its internal store has updated so that React knows those values have changed, allowing it to call setState() and re-render the UI. This happens through an event emitter. The Redux store has a subscribe function, and it takes a callback that provides the new store and, in that function, calls React Redux’s <Provider> component, which calls setState() with the new store value. You can look through the whole implementation here.

Now we have two different parts of our application: the React UI and the Redux store. Neither one can tell the other about events that have been fired.

Implementation

Let’s look at building a simple event emitter. We’ll use a class, and in that class, track the events:

class EventEmitter { public events: Events; constructor(events?: Events) { this.events = events || {}; }
}

Events

We’ll define our events interface. We will store a plain object, where each key will be the named event and its respective value being an array of the callback functions.

interface Events { [key: string]: Function[];
} /**
{ "event": [fn], "event_two": [fn]
}
*/

We’re using an array because there could be more than one subscriber for each event. Imagine the number of times you’d call element.addEventLister("click") in an application… probably more than once.

Subscribe

Now we need to deal with subscribing to a named event. In our simple example, the subscribe() function takes two parameters: a name and a callback to fire.

event.subscribe("named event", value => value);

Let’s define that method so our class can take those two parameters. All we’ll do with those values is attach them to the this.events we’re tracking internally in our class.

class EventEmitter { public events: Events; constructor(events?: Events) { this.events = events || {}; } public subscribe(name: string, cb: Function) { (this.events[name] || (this.events[name] = [])).push(cb); }
}

Emit

Now we can subscribe to events. Next up, we need to fire those callbacks when a new event emits. When it happen, we’ll use event name we’re storing (emit("event")) and any value we want to pass with the callback (emit("event", value)). Honestly, we don’t want to assume anything about those values. We’ll simply pass any parameter to the callback after the first one.

class EventEmitter { public events: Events; constructor(events?: Events) { this.events = events || {}; } public subscribe(name: string, cb: Function) { (this.events[name] || (this.events[name] = [])).push(cb); } public emit(name: string, ...args: any[]): void { (this.events[name] || []).forEach(fn => fn(...args)); }
}

Since we know which event we’re looking to emit, we can look it up using JavaScript’s object bracket syntax (i.e. this.events[name]). This gives us the array of callbacks that have been stored so we can iterate through each one and apply all of the values we’re passing along.

Unsubscribing

We’ve got the main pieces solved so far. We can subscribe to an event and emit that event. That’s the big stuff.

Now we need to be able to unsubscribe from an event.

We already have the name of the event and the callback in the subscribe() function. Since we could have many subscribers to any one event, we’ll want to remove callbacks individually:

subscribe(name: string, cb: Function) { (this.events[name] || (this.events[name] = [])).push(cb); return { unsubscribe: () => this.events[name] && this.events[name].splice(this.events[name].indexOf(cb) >>> 0, 1) };
}

This returns an object with an unsubscribe method. We use an arrow function (() =>) to get the scope of this parameters that are passed to the parent of the object. In this function, we’ll find the index of the callback we passed to the parent and use the bitwise operator (>>>). The bitwise operator has a long and complicated history (which you can read all about). Using one here ensures we’ll always get a real number every time we call splice() on our array of callbacks, even if indexOf() doesn’t return a number.

Anyway, it’s available to us and we can use it like this:

const subscription = event.subscribe("event", value => value); subscription.unsubscribe();

Now we’re out of that particular subscription while all other subscriptions can keep chugging along.

All Together Now!

Sometimes it helps to put all the little pieces we’ve discussed together to see how they relate to one another.

interface Events { [key: string]: Function[];
} export class EventEmitter { public events: Events; constructor(events?: Events) { this.events = events || {}; } public subscribe(name: string, cb: Function) { (this.events[name] || (this.events[name] = [])).push(cb); return { unsubscribe: () => this.events[name] && this.events[name].splice(this.events[name].indexOf(cb) >>> 0, 1) }; } public emit(name: string, ...args: any[]): void { (this.events[name] || []).forEach(fn => fn(...args)); }
}

Demo

See the Pen
Understanding Event Emitters
by Charles (@charliewilco)
on CodePen.

We’re doing a few thing in this example. First, we’re using an event emitter in another event callback. In this case, an event emitter is being used to clean up some logic. We’re selecting a repository on GitHub, fetching details about it, caching those details, and updating the DOM to reflect those details. Instead of putting that all in one place, we’re fetching a result in the subscription callback from the network or the cache and updating the result. We’re able to do this because we’re giving the callback a random repo from the list when we emit the event

Now let’s consider something a little less contrived. Throughout an application, we might have lots of application states that are driven by whether we’re logged in and we may want multiple subscribers to handle the fact that the user is attempting to log out. Since we’ve emitted an event with false, every subscriber can use that value, and whether we need to redirect the page, remove a cookie or disable a form.

const events = new EventEmitter(); events.emit("authentication", false); events.subscribe("authentication", isLoggedIn => { buttonEl.setAttribute("disabled", !isLogged);
}); events.subscribe("authentication", isLoggedIn => { window.location.replace(!isLoggedIn ? "/login" : "");
}); events.subscribe("authentication", isLoggedIn => { !isLoggedIn && cookies.remove("auth_token");
});

Gotchas

As with anything, there are a few things to consider when putting emitters to work.

  • We need to use forEach or map in our emit() function to make sure we’re creating new subscriptions or unsubscribing from a subscription if we’re in that callback.
  • We can pass pre-defined events following our Events interface when a new instance of our EventEmitter class has been instantiated, but I haven’t really found a use case for that.
  • We don’t need to use a class for this and it’s largely a personal preference whether or not you do use one. I personally use one because it makes it very clear where events are stored.

As long as we’re speaking practicality, we could do all of this with a function:

function emitter(e?: Events) { let events: Events = e || {}; return { events, subscribe: (name: string, cb: Function) => { (events[name] || (events[name] = [])).push(cb); return { unsubscribe: () => { events[name] && events[name].splice(events[name].indexOf(cb) >>> 0, 1); } }; }, emit: (name: string, ...args: any[]) => { (events[name] || []).forEach(fn => fn(...args)); } };
}

Bottom line: a class is just a preference. Storing events in an object is also a preference. We could just as easily have worked with a Map() instead. Roll with what makes you most comfortable.


I decided to write this post for two reasons. First, I always felt I understood the concept of emitters made well, but writing one from scratch was never something I thought I could do but now I know I can — and I hope you now feel the same way! Second, emitters are make frequent appearances in job interviews. I find it really hard to talk coherently in those types of situations, and jotting it down like this makes it easier to capture the main idea and illustrate the key points.

I’ve set all this up in a GitHub repo if you want to pull the code and play with it. And, of course, hit me up with questions in the comments if anything pops up!

The post Understanding Event Emitters appeared first on CSS-Tricks.

The Bottleneck of the Web

Steve Souders, “JavaScript Dominates Browser CPU”:

Ten years ago the network was the main bottleneck. Today, the main bottleneck is JavaScript. The amount of JavaScript on pages is growing rapidly (nearly 5x in the last 7 years). In order to keep pages rendering and feeling fast, we need to focus on JavaScript CPU time to reduce blocking the browser main thread.

Alex Russell, describing a prototype of “Never-Slow Mode” in Chrome:

… blocks large scripts, sets budgets for certain resource types (script, font, css, images), turns off document.write(), clobbers sync XHR, enables client-hints pervasively, and buffers resources without Content-Length set.

Craig Hockenberry, posting an idea to the WebKit bug tracker:

Without limits, there is no incentive for a JavaScript developer to keep their codebase small and dependencies minimal. It’s easy to add another framework, and that framework adds another framework, and the next thing you know you’re loading tens of megabytes of data just to display a couple hundred kilobytes of content. …

The situation I’m envisioning is that a site can show me any advertising they want as long as they keep the overall size under a fixed amount, say one megabyte per page. If they work hard to make their site efficient, I’m happy to provide my eyeballs.

It’s easy to point a finger at frameworks and third-party scripts for large amounts of JavaScript. If you’re interested in hearing more about the size of frameworks, you might enjoy me and Dave discussing it with Jason Miller.

And speaking of third-parties, Patrick Hulce created Third Party Web: “This document is a summary of which third-party scripts are most responsible for excessive JavaScript execution on the web today.”

Sometimes name-and-shame is an effective tactic to spark change.

Addy Osmani writes about an ESLint rule that prohibits particular packages, of which you could use to prevent usage of known-to-be-huge packages. So if someone tries to load the entirety of lodash or moment.js, it can be stopped at the linting level.

Tim Kadlec ties the threads together very well in “Limiting JavaScript?” If your gut reaction on this is that JavaScript is being unfairly targeted as a villain, Tim acknowledges that:

One common worry I saw voiced was “if JavaScript, why not other resources too?”. It’s true; JavaScript does get picked on a lot though it’s not without reason. Byte for byte, JavaScript is the most significant detriment to performance on the web, so it does make sense to put some focus on reducing the amount we use.

However, the point is valid. JavaScript may be the biggest culprit more often than not, but it’s not the only one.

The post The Bottleneck of the Web appeared first on CSS-Tricks.

​​Avoiding those dang cannot read property of undefined errors

​​​​Uncaught TypeError: Cannot read property 'foo' of undefined.​ The dreaded error we all hit at some point in JavaScript development. Could be an empty state from an API that returns differently than you expected. Could be something else. We don’t know because the error itself is so general and broad.

​​I recently had an issue where certain environment variables weren’t being pulled in for one reason or another, causing all sorts of funkiness with that error staring me in the face. Whatever the cause, it can be a disastrous error if it’s left unaccounted for, so how can we prevent it in the first place?

​​Let’s figure it out.

​​Utility library

​​If you are already using a utility library in your project, there is a good chance that it includes a function for preventing this error. _.get​ in lodash​ (docs) or R.path in Ramda​ (docs) allow accessing the object safely.
​​
​​If you are already using a utility library, this is likely the simplest solution. If you are not using a utility library, read on!

​​

Short-circuiting with &&

​​​​One interesting fact about logical operators in JavaScript is that they don’t always return a boolean. According to the spec, “the value produced by a &&​ or ||​ operator is not necessarily of type Boolean. The value produced will always be the value of one of the two operand expressions.”
​​
​​​​In the case of the &&​ operator, the first expression will be used if it a “falsy” value. Otherwise, the second expression will be used. This means that the expression 0 && 1​ will be evaluated as 0​ (a falsy value), and the expression 2 && 3​ will be evaluated as 3​. If multiple &&​ expressions are chained together, they will evaluate to either the first falsy value or the last value. For example, 1 && 2 && 3 && null && 4​ will evaluate to null​, and 1 && 2 && 3​ will evaluate to 3​.

​​​​How is this useful for safely accessing nested object properties? Logical operators in JavaScript will “short-circuit.” In this case of &&​, this means that the expression will cease moving forward after it reaches its first falsy value.

​​​​

​​const foo = false && destroyAllHumans();
​​console.log(foo); // false, and humanity is safe

​​In this example, destroyAllHumans is never called because the &&​ operand stopped all evaluation after false​.

​​This can be used to safely access nested properties.

​​

​​const meals = {
​​ breakfast: null, // I skipped the most important meal of the day! :(
​​ lunch: {
​​ protein: 'Chicken',
​​ greens: 'Spinach',
​​ },
​​ dinner: {
​​ protein: 'Soy',
​​ greens: 'Kale',
​​ },
​​};
​​
​​const breakfastProtein = meals.breakfast && meals.breakfast.protein; // null
​​const lunchProtein = meals.lunch && meals.lunch.protein; // 'Chicken'

​​Aside from its simplicity, one of the main advantages of this approach is its brevity when dealing with small chains. However, when accessing deeper objects, this can be quite verbose.

​​

const favorites = {
​​ video: {
​​ movies: ['Casablanca', 'Citizen Kane', 'Gone With The Wind'],
​​ shows: ['The Simpsons', 'Arrested Development'],
​​ vlogs: null,
​​ },
​​ audio: {
​​ podcasts: ['Shop Talk Show', 'CodePen Radio'],
​​ audiobooks: null,
​​ },
​​ reading: null, // Just kidding -- I love to read
​​};
​​
​​const favoriteMovie = favorites.video && favorites.video.movies && favorites.video.movies[0];
​​// Casablanca
​​const favoriteVlog = favorites.video && favorites.video.vlogs && favorites.video.vlogs[0];
​​// null

​​The more deeply nested an object is, the more unwieldy it gets.

​​
​​

The “Maybe Monad”

​​Oliver Steele came up with this method and goes through it in much more detail in his blog post, “Monads on the Cheap I: The Maybe Monad.” I will attempt to give a brief explanation here.

​​

const favoriteBook = ((favorites.reading||{}).books||[])[0]; // undefined
​​const favoriteAudiobook = ((favorites.audio||{}).audiobooks||[])[0]; // undefined
​​const favoritePodcast = ((favorites.audio||{}).podcasts||[])[0]; // 'Shop Talk Show'

​​Similar to the short-circuit example above, this method works by checking if a value is falsy. If it is, it will attempt to access the next property on an empty object. In the example above, favorites.reading​ is null​, so the books​ property is being accessed from an empty object. This will result in an undefined​, so the 0​ will likewise be accessed from an empty array.

​​The advantage of this method over the &&​ method is that it avoids repetition of property names. On deeper objects, this can be quite a significant advantage. The primary disadvantage would be readability — it is not a common pattern, and may take a reader a moment to parse out how it is working.​

​​

​​try/catch

​​​​try...catch​ statements in JavaScript allow another method for safely accessing properties.

​​

try {
​​ console.log(favorites.reading.magazines[0]);
​​} catch (error) {
​​ console.log("No magazines have been favorited.");
​​}

​​Unfortunately, in JavaScript, try...catch​ statements are not expressions. They do not evaluate to a value as they do in some languages. This prevents a concise try​ statement as a way of setting a variable.

​​One option is to use a let​ variable that is defined in the block above the try...catch​.

​​

let favoriteMagazine;
​​try { ​​ favoriteMagazine = favorites.reading.magazines[0]; ​​} catch (error) { ​​ favoriteMagazine = null; /* any default can be used */
​​};

​​Although it’s verbose, this works for setting a single variable (that is, if the mutable variable doesn’t scare you off). However, issues can arise if they’re done in bulk.

​​

let favoriteMagazine, favoriteMovie, favoriteShow;
​​try {
​​ favoriteMovie = favorites.video.movies[0];
​​ favoriteShow = favorites.video.shows[0];
​​ favoriteMagazine = favorites.reading.magazines[0];
​​} catch (error) {
​​ favoriteMagazine = null;
​​ favoriteMovie = null;
​​ favoriteShow = null;
​​};
​​
​​console.log(favoriteMovie); // null
​​console.log(favoriteShow); // null
​​console.log(favoriteMagazine); // null

​​If any of the attempts to access the property fails, this will cause all of them to fall back into their defaults.

​​An alternative is to wrap the try...catch​ in a reusable utility function.

​​

const tryFn = (fn, fallback = null) => {
​​ try {
​​ return fn();
​​ } catch (error) {
​​ return fallback;
​​ }
​​} ​​
​​const favoriteBook = tryFn(() => favorites.reading.book[0]); // null
​​const favoriteMovie = tryFn(() => favorites.video.movies[0]); // "Casablanca"

​​By wrapping the access to the object in a function, you can delay the “unsafe” code and pass it into a try...catch​.

​​A major advantage of this method is how natural it is to access the property. As long as properties are wrapped in a function, they are safely accessed. A default value can also be specified in the case of a non-existent path.

​​Merge with a default object

​​
By merging an object with a similarly shaped object of “defaults,” we can ensure that the path that we are trying to access is safe.
​​
​​

const defaults = {
​​ position: "static",
​​ background: "transparent",
​​ border: "none",
​​};
​​
​​const settings = {
​​ border: "1px solid blue",
​​};
​​
​​const merged = { ...defaults, ...settings };
​​
​​console.log(merged); ​​/*
​​ {
​​ position: "static",
​​ background: "transparent",
​​ border: "1px solid blue"
​​ }
​​*/

​​
​​Careful, though, because the entire nested object can be overwritten rather than a single property.
​​
​​

const defaults = {
​​ font: {
​​ family: "Helvetica",
​​ size: "12px",
​​ style: "normal",
​​ }, ​​ color: "black",
​​};
​​
​​const settings = {
​​ font: {
​​ size: "16px",
​​ }
​​};
​​
​​const merged = { ​​ ...defaults, ​​ ...settings,
​​};
​​
​​console.log(merged.font.size); // "16px"
​​console.log(merged.font.style); // undefined

​​Oh no! To fix this, we’ll need to similarly copy each of the nested objects.

​​

const merged = { ​​ ...defaults, ​​ ...settings,
​​ font: {
​​ ...defaults.font,
​​ ...settings.font,
​​ },
​​};
​​
​​console.log(merged.font.size); // "16px"
​​console.log(merged.font.style); // "normal"

​​Much better!

​​This pattern is common with plugins or components that accept a large settings object with included defaults.

​​A bonus about this approach is that, by writing a default object, we’re including documentation on how an object should look. Unfortunately, depending on the size and shape of the data, the “merging” can be littered with copying each nested object.

​​​

The future: optional chaining

​​There is currently a TC39 proposal for a feature called “optional chaining.” This new operator would look like this:

​​console.log(favorites?.video?.shows[0]); // 'The Simpsons'
​​console.log(favorites?.audio?.audiobooks[0]); // undefined

​​The ?.​ operator works by short-circuiting: if the left-hand side of the ?.​ operator evaluates to null​ or undefined​, the entire expression will evaluate to undefined​ and the right-hand side will remain unevaluated.

​​To have a custom default, we can use the ||​ operator in the case of an undefined.

​​

console.log(favorites?.audio?.audiobooks[0] || "The Hobbit");

​​

Which method should you use?

​​The answer, as you might have guessed, is that age-old answer… “it depends.” If the optional chaining operator has been added to the language and has the necessary browser support, it is likely the best option. If you are not from the future, however, there are more considerations to take into account. Are you using a utility library? How deeply nested is your object? Do you need to specify defaults? Different cases may warrant a different approach.

The post ​​Avoiding those dang cannot read property of undefined errors appeared first on CSS-Tricks.

A Funny Thing Happened on the Way to the JavaScript

Around this time last year, I wrote an article about the JavaScript learning landscape. Within that article, you’ll find my grand plans to learn JavaScript — complete with a link to a CodePen Collection I started for tracking my progress, and it even got dozens of comments cheering me on.

Like most people, I was ambitious. It was a new year and I was excited to tackle a long-standing project. It was my development version of losing 30 pounds (which I also need to do). But, if you follow that link to the CodePen Collection, you’ll see that there’s nothing there. If you were to scour my hard drive or cloud storage, you’d see that there aren’t any JavaScript files or projects there, either.

Over the past year, I didn’t make any progress on one of my main goals. So, what the hell happened?

A Story as Old as Time

The internet is littered with similar tweets and blog posts. Inboxes are filled with TinyLetters of resolutions and there’s no shortage of YouTubers teaching anyone who will listen how to have their best year ever. But very few people follow through on their goals. This might be even more true in the design and development world, what with the plethora of new technologies, languages, libraries, and tools that hit the scene on a regular basis.

These stories all follow a similar path:

  1. Person determines major goal
  2. Person tells friends (or who knows how many CSS-Tricks visitors)
  3. Person gets distracted, overwhelmed, disinterested, or all three
  4. Goal is completely forgotten about after X amount of time
  5. Person apologizes and makes up excuses for friends (or, again, who know how many CSS-Tricks visitors)

In my experience, it’s not the goal-setting or telling everyone about said goal that’s the problem. It’s step three above. When goals go off the rails, at least for me, it’s due to three main issues: distraction, stress, and lack of interest. Barring unforeseen life events, these three issues are responsible for all those unachieved goals that we struggle with.

In thinking about my goals for this year, I decided to start first with deconstructing why I couldn’t reach the one major goal I set for myself last year. So, let’s dig into those three issues and see if there’s a way to prevent any of them happening this time around.

Distraction

Distraction seems to be the big one here. We all have a lot going on. Between job and family responsibilities, other hobbies and hanging out with friends, it’s hard to fit in new projects. As necessary as they are, all those other interests and responsibilities are distractions when it comes to our goals.

The whole point of setting a goal is carving out time to work towards it. It’s about prioritizing the goal over other things. For me, I found myself letting all of those other distractions in life work their way into my day. It was all too easy to work through lunch instead of taking that time to tackle a chapter in a JavaScript book. I would get sucked into the latest Netflix series after the kids went to bed. I didn’t prioritize learning JavaScript and I had nothing to show for it at the end of the year.

Overcoming Distraction

The key here is to block out those distractions, which is easier said than done. We can’t simply ignore the needs of our families and careers, but we need to give ourselves time to focus without distractions. For me, I’m increasingly convinced that the solution is time blocking.

Time blocking is exactly what it sounds like: You block out specific periods of time on your calendar to focus on certain tasks. Time blocking allows you to prioritize what’s important. It doesn’t force you to sit down, crack open a book, or start coding, but it gives you the time to do it.
There are a ton of articles online that go into different time blocking methods, a few of which are below:

For me, I’m going to block out specific times throughout the week to focus on learning JavaScript in 2019. I’m trying to be realistic about how much time I can invest, weighing it against other obligations. Then I’m putting those time blocks on my shared family calendar to make it clear to everyone what I’m prioritizing. More importantly, I’m making it clear that this time is for focus, and to leave the other distractions at the door.

It can also be helpful to block smaller, but just as impactful, distractions on your phone and computer. Closing out browser tabs not related to your task, silencing notifications, and clearing your desk of otherwise distracting items should be part of the routine when you sit down to start working on your task. It’s easy to scroll through Twitter, Hacker News, or even CSS-Tricks and convince yourself that it’s time well spent (that last one usually is, though) but that time adds up and doesn’t always result in learning or growing your skills like you think it will. Cutting out those distractions and allowing yourself to focus on what you want to accomplish is a great way to, you know, actually accomplish your goals.

Stress

Last year’s post lays out a landscape full of interesting articles, books, podcasts, and courses. There is no lack of things to learn about and enough resources to keep anyone busy for way longer than just a year. And, when it comes to JavaScript, it seems like there’s always some new technique or framework that you need to learn.

Combine that with all of the ancillary topics you need to understand when learning JavaScript and you end up with one of those overwhelming developer roadmaps that Chris collected a while back.

I don’t care how smart you are, that’s intimidating as hell. Feeling overwhelmed on the web is common place. How do you think it feels as someone just starting out? Combined with all the responsibilities and distractions from the last section, and you have a killer recipe for burnout.

I had originally intended to work my way through Marijn Haverbeke’s Eloquent JavaScript as a first step towards learning the language. But I also mentioned all the podcasts, YouTube channels, and newsletters with which I was surrounding myself. The intention was to learn through immersion, but it quickly resulted in feeling stressed and overwhelmed. And when I felt overwhelmed, I quickly allowed all those distractions to pull my attention away from learning JavaScript.

Overcoming Stress

Just like when dealing with distraction, I think the key to dealing with stress is to focus on one or two things and cut out all the rest. Instead of fully immersing myself in the JavaScript world, I’m going to stick to just the book, work my way through that, and then find the next resource later down the road. I’m going to intentionally ignore as much of the JavaScript world as I can in order to get my bearings and only open myself up to the stress of the developer roadmap if, and when, I feel like I want to journey down that path.

Disinterest

Flipping through any programming book (at least for a beginner) causes most people’s eyes to glaze over. The code looks overly complex and it resembles a math textbook. I don’t know about you, but I hated math class and I found it hard to get excited about investing my free time in something that felt a lot like going back to high school.

But I know that learning JavaScript (and programming, in general) is a worthwhile pursuit and will let me tackle projects that I’ve long wanted to complete but haven’t had the chops to do. So, how can I get interested in what, at first glance, looks like such a boring task?

Overcoming Disinterest

I think the key here is to relate what I learn to some subject that I find fascinating.

I’ve been interested in data visualization for a long time. Blogs like Flowing Data are fascinating, and I’ve wanted to be able to create data visualizations of my own for years. And I know that JavaScript is increasingly a viable way to create those graphics. Tools like D3.js and p5.js are first-class frameworks for creating amazing visualizations — so why not learn the underlying language those tools use?

My plan to overcome disinterest is to work my way towards a project that I want to build. Go through all the basics, trudge through the muck, and then use the concepts learned along the way to understand more advanced tools, like D3.js.

Anytime you can align your learning to areas you find interesting, you’re more likely to be successful. I think that’s what was missing the first time around, so I’m setting up targets to aim for when learning JavaScript, things that will keep me interested enough to learn what I need to learn.

It’s a Hard Road

Learning is rarely easy. But, sometimes, it’s when it’s the hardest that it pays off the most.

I’m convinced that the more we can uncover our own mental roadblocks and deconstruct them, the better positioned we are to achieve our goals. For me, my mental roadblocks are distraction, stress, and disinterest. The three work together to keep me from my goals, but I’m putting plans into motion to overcome all three. Your roadblocks may differ, but you probably have ways of dealing with them, too.

I’d love to hear from everyone how they overcame their own challenges when learning a new skill. Leave a comment below telling me your story. Sharing it may help me, and others, finally achieve what we’ve always wanted, whether it’s learning JavaScript, digging into the latest framework, or running that marathon we’ve all been putting off for so long.

The post A Funny Thing Happened on the Way to the JavaScript appeared first on CSS-Tricks.

You might not need a loop

Ire Aderinokun has written a nifty piece using loops and when we might consider replacing it with another method, say .map() and .filter(). I particularly like what she has to say here:

As I mentioned earlier, loops are a great tool for a lot of cases, and the existence of these new methods doesn’t mean that loops shouldn’t be used at all.

I think these methods are great because they provide code that is in a way self-documenting. When we use the filter() method instead of a for loop, it is easier to understand at first glance what the purpose of the logic is.

However, these methods have very specific use cases and may be overkill if their full value isn’t being used. An example of this is the map() method, which can technically be used to replace almost any arbitrary loop. If in our first example, we only wanted to modify the original articles array and not create a new, modified, amazingArticles, using this method would be unnecessary. It’s important to use the method that suits each scenario, to make sure that we aren’t over- or under-performing.

If you’re interested in digging more into this subject, Adan Giese wrote a great post about the .filter() method a short while ago that’s definitely worth checking out. Oh, and speaking of lots of different ways to approach loops, Chris compiled a list of options for looping over querySelectorAll NodeLists where forEach is just one of many options.

Direct Link to ArticlePermalink

The post You might not need a loop appeared first on CSS-Tricks.

A Bunch of Options for Looping Over querySelectorAll NodeLists

A common need when writing vanilla JavaScript is to find a selection of elements in the DOM and loop over them. For example, finding instances of a button and attaching a click handler to them.

const buttons = document.querySelectorAll(".js-do-thing");
// There could be any number of these! // I need to loop over them and attach a click handler.

There are SO MANY ways to go about it. Let’s go through them.

forEach

forEach is normally for arrays, and interestingly, what comes back from querySelectorAll is not an array but a NodeList. Fortunately, most modern browsers support using forEach on NodeLists anyway.

buttons.forEach((button) => { button.addEventListener('click', () => { console.log("forEach worked"); });
});

If you’re worried that forEach might not work on your NodeList, you could spread it into an array first:

[...buttons].forEach((button) => { button.addEventListener('click', () => { console.log("spread forEach worked"); });
});

But I’m not actually sure if that helps anything since it seems a bit unlikely there are browsers that support spreads but not forEach on NodeLists. Maybe it gets weird when transpiling gets involved, though I dunno. Either way, spreading is nice in case you want to use anything else array-specific, like .map(), .filter(), or .reduce().

A slightly older method is to jack into the array’s natural forEach with this little hack:

[].forEach.call(buttons, (button) => { button.addEventListener('click', () => { console.log("array forEach worked"); });
});

Todd Motto once called out this method pretty hard though, so be advised. He recommended building your own method (updated for ES6):

const forEach = (array, callback, scope) => { for (var i = 0; i < array.length; i++) { callback.call(scope, i, array[i]); }
};

…which we would use like this:

forEach(buttons, (index, button) => { console.log("our own function worked");
});

for .. of

Browser support for for .. of loops looks pretty good and this seems like a super clean syntax to me:

for (const button of buttons) { button.addEventListener('click', () => { console.log("for .. of worked"); });
}

Make an array right away

const buttons = Array.prototype.slice.apply( document.querySelectorAll(".js-do-thing")
);

Now you can use all the normal array functions.

buttons.forEach((button) => { console.log("apply worked");
});

Old for loop

If you need maximum possible browser support, there is no shame in an ancient classic for loop:

for (let i = 0; i < buttons.length; ++i) { buttons[i].addEventListener('click', () => { console.log("for loop worked"); });
}

Libraries

If you’re using jQuery, you don’t even have to bother….

$(".buttons").on("click", () => { console.log("jQuery works");
});

If you’re using a React/JSX setup, you don’t need think about this kind of binding at all.

Lodash has a _.forEach as well, which presumably helps with older browsers.

_.forEach(buttons, (button, key) => { console.log("lodash worked");
});

Poll

Twitter peeps:

Also here’s a Pen with all these options in it.

The post A Bunch of Options for Looping Over querySelectorAll NodeLists appeared first on CSS-Tricks.

Demystifying JavaScript Testing

Many people have messaged me, confused about where to get started with testing. Just like everything else in software, we work hard to build abstractions to make our jobs easier. But that amount of abstraction evolves over time, until the only ones who really understand it are the ones who built the abstraction in the first place. Everyone else is left with taking the terms, APIs, and tools at face value and struggling to make things work.

One thing I believe about abstraction in code is that the abstraction is not magic — it’s code. Another I thing I believe about abstraction in code is that it’s easier to learn by doing.

Imagine that a less seasoned engineer approaches you. They’re hungry to learn, they want to be confident in their code, and they’re ready to start testing. 👍 Ever prepared to learn from you, they’ve written down a list of terms, APIs, and concepts they’d like you to define for them:

  • Assertion
  • Testing Framework
  • The describe/it/beforeEach/afterEach/test functions
  • Mocks/Stubs/Test Doubles/Spies
  • Unit/Integration/End to end/Functional/Accessibility/Acceptance/Manual testing

So…

Could you rattle off definitions for that budding engineer? Can you explain the difference between an assertion library and a testing framework? Or, are they easier for you to identify than explain?

Here’s the point. The better you understand these terms and abstractions, the more effective you will be at teaching them. And if you can teach them, you’ll be more effective at using them, too.

Enter a teach-an-engineer-to-fish moment. Did you know that you can write your own assertion library and testing framework? We often think of these abstractions as beyond our capabilities, but they’re not. Each of the popular assertion libraries and frameworks started with a single line of code, followed by another and then another. You don’t need any tools to write a simple test.

Here’s an example:

const {sum} = require('../math')
const result = sum(3, 7)
const expected = 10
if (result !== expected) { throw new Error(`${result} is not equal to ${expected}`)
}

Put that in a module called test.js and run it with node test.js and, poof, you can start getting confident that the sum function from the math.js module is working as expected. Make that run on CI and you can get the confidence that it won’t break as changes are made to the codebase. 🏆

Let’s see what a failure would look like with this:

Terminal window showing an error indicating -4 is not equal to 10.

So apparently our sum function is subtracting rather than adding and we’ve been able to automatically detect that through this script. All we need to do now is fix the sum function, run our test script again and:

Terminal window showing that we ran our test script and no errors were logged.

Fantastic! The script exited without an error, so we know that the sum function is working. This is the essence of a testing framework. There’s a lot more to it (e.g. nicer error messages, better assertions, etc.), but this is a good starting point to understand the foundations.

Once you understand how the abstractions work at a fundamental level, you’ll probably want to use them because, hey, you just learned to fish and now you can go fishing. And we have some pretty phenomenal fishing polls, uh, tools available to us. My favorite is the Jest testing platform. It’s amazingly capable, fully featured and allows me to write tests that give me the confidence I need to not break things as I change code.

I feel like fundamentals are so important that I included an entire module about it on TestingJavaScript.com. This is the place where you can learn the smart, efficient way to test any JavaScript application. I’m really happy with what I’ve created for you. I think it’ll help accelerate your understanding of testing tools and abstractions by giving you the chance to implement parts from scratch. The (hopeful) result? You can start writing tests that are maintainable and built to instill confidence in your code day after day. 🎣

The early bird sale is going on right now! 40% off every tier! The sale is going away in the next few days so grab this ASAP!

TestingJavaScript.com – Learn the smart, efficient way to test any JavaScript application.

P.S. Give this a try: Tweet what’s the difference between a testing framework and an assertion library? In my course, I’ll not only explain it, we’ll build our own!

The post Demystifying JavaScript Testing appeared first on CSS-Tricks.

How to stop using console.log() and start using your browser’s debugger

Whenever I see someone really effectively debug JavaScript in the browser, they use the DevTools tooling to do it. Setting breakpoints and hopping over them and such. That, as opposed to sprinkling console.log() (and friends) statements all around your code.

Parag Zaveri wrote about the transition and it has clearly resonated with lots of folks! (7.5k claps on Medium as I write).

I know I have hangups about it…

  • Part of debugging is not just inspecting code once as-is; it’s inspecting stuff, making changes and then continuing to debug. If I spend a bunch of time setting up breakpoints, will they still be there after I’ve changed my code and refreshed? Answer: DevTools appears to do a pretty good job with that.
  • Looking at the console to see some output is one thing, but mucking about in the Sources panel is another. My code there might be transpiled, combined, and not quite look like my authored code, making things harder to find. Plus it’s a bit cramped in there, visually.

But yet! It’s so powerful. Setting a breakpoint (just by clicking a line number) means that I don’t have to litter my own code with extra junk, nor do I have to choose what to log. Every variable in local and global scope is available for me to look at that breakpoint. I learned in Parag’s article that you might not even need to manually set breakpoints. You can, for example, have it break whenever a click (or other) event fires. Plus, you can type in variable names you specifically want to watch for, so you don’t have to dig around looking for them. I’ll be trying to use the proper DevTools for debugging more often and seeing how it goes.

While we’re talking about debugging though… I’ve had this in my head for a few months: Why doesn’t JavaScript have log levels? Apparently, this is a very common concept in many other languages. You can write logging statements, but they will only log if the configuration says it should. That way, in development, you can get detailed logging, but log only more serious errors in production. I mention it because it could be nice to leave useful logging statements in the code, but not have them actually log if you set like console.level = "production"; or whatever. Or perhaps they could be compiled out during a build step.

Direct Link to ArticlePermalink

The post How to stop using console.log() and start using your browser’s debugger appeared first on CSS-Tricks.