Today I Learned

A Hashrocket project

Preventing access to `Window.opener`

When you open a link in a new tab with target="_blank" like so:

<a target="_blank" href="">Somewhere</a>

Then the page that you open has access to the original page through Window.opener. Depending on your case you may not want this. Actually I can’t think of a case where you do want the new tab to refer back to the opening tab.

To prevent Window.opener access use rel="noopener":

<a target="_blank" href="" rel="noopener">Somelink</a>

At this moment, this is not available in IE or Edge, check out the caniuse site.

H/T Dillon Hafer

Use jq to filter objects list with regex

My use case is filtering an array of objects that have an attribute that matches a particular regex and extract another attribute from that object.

Here is my dataset:

  {name: 'Chris', id: 'aabbcc'},
  {name: 'Ryan', id: 'ddeeff'},
  {name: 'Ifu', id: 'aaddgg'}

First get each element of an array.

> data | jq '.[]'
{name: 'Chris', id: 'aabbcc'}
{name: 'Ryan', id: 'ddeeff'}
{name: 'Ifu', id: 'aaddgg'}

Pipe the elements to select and pass an expression that will evaluate to truthy for each object.

> data | jq '.[] | select(true) | select(.name)'
{name: 'Chris', id: 'aabbcc'}
{name: 'Ryan', id: 'ddeeff'}
{name: 'Ifu', id: 'aaddgg'}

Then use the test function to compare an attribute to a regex.

> data | jq '.[] | select(.id|test("a."))'
{name: 'Chris', id: 'aabbcc'}
{name: 'Ifu', id: 'aaddgg'}

Extract the name attribute for a more concise list.

> data | jq '.[] | select(.id|test("a.")) | .name'

Read more about jq

Inactive And Active Component Styles With Radium

Radium is “toolchain for React component styling” allowing you to do comprehensive inline styling with CSS.

Often times, especially in the case of a series of nav elements, there is a need to style one element as active while styling the rest as inactive. This can be achieved with Radium by defining two groups of styles (base and active) and then relying on props to conditionally apply the active style.

import React from 'react';
import Radium from 'radium';

const styles = {
  base: {
    textDecoration: "none",
    color: "gray",
  active: {
    color: "black",
    backgroundColor: "lightgray",

let NavItem = ({ label, path, active }) => {
  return (
        styles[active && 'active'],

NavItem = Radium(NavItem);

With Radium, our base (inactive) styles always get applied. Then, the active styles only get applied when the active prop is true. We produce a Radium-ified version of our NavItem on the last line so that Radium can handle all of the styling of the component.

Setting Struct properties with an index

It’s rare that I get a chance to use structs but yesterday while parsing some xml (!!!) I wrote an algorythm where it would be handy to set values of a struct with an incrementing number rather than a symbol.

Low and Behold! Ruby Structs allow you to set attributes with either the name of the property or the ordinal with which it was declared.

2.5.0 :001 > Apple =, :size)
 => Apple
2.5.0 :002 > apple =
 => #<struct Apple color=nil, size=nil>
2.5.0 :003 > apple[0] = 'red'
 => "red"
2.5.0 :004 > apple[1] = 'huge'
 => "huge"
2.5.0 :005 > apple
 => #<struct Apple color="red", size="huge">

Structs are a great data structure that I’m going to try to use more in my daily programming.

Setting timezones from command line on MacOS

We wrote some tests that failed recently in a timezone other than our own (☹️). In order to reproduce this failure we had to set the timezone of our local machine to the failure timezone.

sudo systemsetup -settimezone America/New_York

Easy enough. You can get all the timezones available to you with:

sudo systemsetup -listtimezones

And also check your current timezone

sudo systemsetup -gettimezone

systemsetup has 47 different time/system oriented commands. But it needs a sudo even to run -help.

> systemsetup -help
You need administrator access to run this tool... exiting!

Don’t fret you can get this important secret information via the man page

man systemsetup

Rendering Multiple Nodes With Fragments

When rendering, React expects a component to only return a single node. The DOM hierarchy of most components will easily follow this rule, but what about those components that do have multiple inline nodes?

The two solutions have been to either wrap the inline nodes in an outer div or to return them as a comma separated array of nodes. With React 16, we can avoid the deficiencies of both of these approaches by using a fragment.

Just wrap your inline nodes with a React.Fragment node. React will understand your JSX without wrapping the output DOM in a superfluous div.

render() {
  // ... more code

  return (
      <p>Name: {firstName} {lastName}</p>
      <p>Email: {email}</p>
      <p>Age: {age}</p>

See the docs on fragments for more details.

Fill An Input With A Ton Of Text

I needed to test out a form validation for an input that should render an error when the length of the context exceeds 10,000 characters. Two small tricks make this easy.

First, you can target any DOM element via the Chrome dev tools by selecting it and then referencing it via the $0 magic variable. More details here.

> $0

Second, you can quickly and precisely generate a very long string with the repeat function.

> "a".repeat(10000)

Combine these two tricks in the browser to fill the input with a ton of text:

> $0.value = "a".repeat(10000)

h/t Dillon Hafer

Log rotation in ruby

Jake wrote a great til about linux log rotation last year. Ruby also has a log rotation alternative built into the stdlib.

Generally, ruby logging looks like this:

require 'logger'
logger ='app.log')'starting log')

You can also pass a ‘daily’, ‘weekly’ or ‘monthly’ to the logger:

logger ='week.log', 'weekly')

If I use this log today, Tue Jan 9, and next week on Wed Jan 17, then ls will show two log files:


20180113 is Saturday the last day of the previous logging period, a new log is started every Sunday. NOTE: no files are deleted with this style of logging, you may potentially run out of space.

You can also choose to log with the number of files to keep and the maximum size of each file.

logger ='size.log', 4, 1024000)

In this case after producing more than 4 MB of logging information ls will show you.


Compared to linux’s logrotate this is missing features, compression for example, but for adding log rotation to your logs quickly and simply it works great.


flex-flow for shorter flex declarations

flex-flow is a css property that allows you to specify both flex-direction and flex-wrap in one property. In css parlance this is a shorthand property and like all shorthand properties the values are order agnostic when possible.

It will provide minimal efficiency gains but you can just avoid writing flex-direction altogether. When you need to specify a direction just type:

ul { 
  display: flex;
  flex-flow: row;

And then its easy to tack on a wrap when you determine it is necessary:

ul {
  display: flex;
  flex-flow: row wrap;

Native CSS Variables

CSS variables are normally associated with the pre-processor languages like SASS. But css has its own native variables as well. Declare them like so:

element { 
  --black-grey: #111111;

And then use them with the var function like this:

element { 
  background-color: var(--black-grey);

In the above example if --black-grey is not set then the background-color will fallback to the inherited value. You can provide a default value for the variable if you anticipate it may not be set:

element {
  background-color: var(--black-grey, black);

Variables behave just like any other inherited or cascading properties and if you’d like them available for entire stylesheets then you would need to declare them in :root.

:root {
  --one-fathom: 16rem;

This css feature is safe to use everywhere but IE, but it is only recently safe. Firefox enabled this feature by default in version 56 released in Sept 2017.

You can read about them in the Mozilla Docs or the original W3C editor’s draft.

zsh change dir after hook w/`chpwd_functions`

How does rvm work? You change to a directory and rvm has determined which version of ruby you’re using.

In bash, the cd command is overriden with a cd function. This isn’t necessary in zsh because zsh has hooks that execute after you change a directory.

If you have rvm installed in zsh you’ll see this:

> echo $chpwd_functions
> echo ${(t)chpwd_functions}

chpwd_functions is an array of functions that will be executed after you run cd.

Within the function you can use the $OLDPWD and $PWD env vars to programatically determine where you are like this:

> huh() { echo 'one sec...' echo $OLDPWD && echo $PWD } 
> chpwd_functions+=huh
> cd newdir
one sec...

You can read more about hook functions in the zsh docs.

Comply with the erlang IO protocol

Below is a basic IO server/device implementation, it receives an :io_request message and responds with a :io_reply message.

defmodule MYIODevice do
  def listen() do
    receive do
      {:io_request, from, reply_as, {:put_chars, :unicode, message}} ->
        send(from, {:io_reply, reply_as, :ok})
        IO.puts("I see you")

pid = spawn_link(MYIODevice, :listen, [])

IO.puts(pid, "Hey there")

The above code outputs the following to stdout:

Hey there
I see you

The first argument of IO.puts/2 is a pid representing the device that is being written to, it is generally defaulted to :stdio)

The documentation is dense, enjoy! Erlang IO Protocol

H/T Brian Dunn

Postgres locale settings are inherited from OS

By default, postgres inherits locale settings from operating system, which can greatly affect sort. Comparing linux and unix, both using the locale en_US.UTF-8, we see the following sort outputs:


select name from unnest(array['No one', 'None', ' Not']) name order by name;
No one


select name from unnest(array['No one', 'None', ' Not']) name order by name;
No one

You’ll notice that on the linux system, whitespaces are ignored during sorting.

To get consistent behavior across operating systems, you can use the postgres provided C locale:

select name from unnest(array['No one', 'None', ' Not']) name order by name collate 'C';
No one

Remove duplicates in zsh $PATH

How to do it?

typeset -aU path

There ya go. All entries in $PATH are now unique

How does it work? Well that’s stickier. path and PATH are not the same thing. You can determine that by examining the type of each with t variable expansion.

> echo ${(t)path}
> echo ${(t)PATH}

They are linked variables however, if you change one you change the other but they have different properties. I have to admit at this point that scalar-export-special is something of which I’m ignorant.

The typeset declaration is simpler, it changes the type of path from array-special to array-unique-special. The -a flag is for array and the -U flag is for unique.

Page and Search Through MySQL

Need to explore results in the MySQL REPL? The pager command can help.

Let’s set our pager of choice (we’ll use Less):

mysql> pager less
PAGER set to 'less'

Then, execute the query:

mysql> select * from users;

The result will be loaded in the Less pager. From here, we can navigate or search through the results.

Leave the custom pager with \n:

mysql> \n
PAGER set to stdout

What files are being sourced by zsh at startup?

Tracking down a bug in the jagged mountains of shell files that are my zsh configuration can be tough. Enter the SOURCE_TRACE option, settable with the -o flag when opening a new shell with the zsh command.


Which outputs:

+/etc/zsh/zshenv:1> <sourcetrace>
+/etc/zsh/zshrc:1> <sourcetrace>
+/home/chris/.zshrc:1> <sourcetrace>
+/home/chris/.sharedrc:1> <sourcetrace>
+/home/chris/.zshrc.local:1> <sourcetrace>

The above output is an abbreviated representation of the actual files loaded on my system. I have language manager asdf installed which adds a couple of entries. I am an rvm user which adds 50 (!!!) entries. Lots of shell code to source for rvm. Additionally, I use Hashrocket’s dotmatrix which adds even more entries. Lots of sourcing to sort through.

This is handy in combination with print line (or echo) debugging. It gives your print lines added context with things get noisy.

Treat words with dash as a word in Vim

By default vim treats two words connected with an underscore e.g. search_tag as a vim word text-object.

This is very useful because you can then use motions and commands on them such as daw to delete a word, or ciw to change inside the word.

That is not the case for dash separated words e.g. search-tag. These types of words are very common in CSS class names and HTML IDs.

To make vim treat dash separated words as a word text-object simply add the following to your .vimrc:

set iskeyword+=-

And source it again.

Jump between #git hunks in Vim with vim-gitgutter

One of my favorite Vim plugins is vim-gitgutter - it shows gutter markings for changes in the current buffer when that file is tracked by git.

It looks like this:

+ = new lines - = deleted line ~ = changed line

It also comes with a few very useful commands for working with hunks, sections of changed code in your file.

To jump between hunks you can use ]c and [c. Since I don’t really use the return and backspace keys in normal mode I have mapped those instead:

nnoremap <silent> <cr> :GitGutterNextHunk<cr>
nnoremap <silent> <backspace> :GitGutterPrevHunk<cr>

This is especially useful on big files (more than a bufferful) with scattered changes.

Killing heroku dynos

Yesterday we encountered an odd situation. A rake task running with heroku that did not finish. Through no fault of our own.

We killed the local processes kicked off by the heroku command line tool and restarted the rake task but got an error message about only allowing one free dyno. Apparently, the dyno supporting our rake task was still in use.

First we had to examine whether that was true with:

heroku ps -a myapp

Next step was to kill the dyno with the identifier provided by the above command.

heroku ps:kill dyno.1 -a myapp

We ran the rake task again, everything was fine, it worked great.

sub_filter + proxy_pass requires no gzip encoding

The nginx sub module is useful for injecting html into web requests at the nginx level. It looks like this:

location / {
  sub_filter '</head>' '<script>doSomething();</script></head>';

Replace the end closing tag with a script tag and the head closing tag.

This does not work however with the proxy_pass module response coming from the proxy_pass url is gzip encoded.

In this case, you want to specify to the destination server that you will accept no encoding whatoever with the proxy_set_header directive, like so:

  proxy_set_header Accept-Encoding "";

Altogether it looks like this:

location / {
  proxy_set_header Accept-Encoding "";
  sub_filter '</head>' '<script>doSomething();</script></head>';

Examine owner and permissions of paths

The ownership of an entire path hierarchy is important when nginx needs to read static content. For instance, the path /var/www/ may be problematic when directory three is owned by root rather than www-data. Nginx will respond with status code 403 (forbidden) when is accessed.

To debug this scenario we need to examine the owners and pemissions of each of the directories that lead to numbers.html. This can be accomplished in linux with the handy namei command in combination with realpath.

Real path will return the fullpath for the file.

> realpath numbers.html

And namei -l <full_path> will examine each step in the file’s directory structure.

> namei -l $(realpath numbers.html)
drwxr-xr-x root  root  /
drwxr-xr-x root  root  var
drwxr-xr-x www-data www-data www
drwxr-xr-x www-data www-data
drwxr-xr-x www-data www-data one
drwxr-xr-x root root two
drwxr-xr-x www-data www-data three
-rw-r--r-- www-data www-data numbers.html

Ah there it is. The directory two is owned by root rather that www-data. chown will help you from here.

Cursor Pagination with graphql

When a graphql object has a plural type, each object of the collection from that plural type will have a cursor associated with it. This cursor is generally a base64 encoded unique identifier referencing the search, the object and the place of that object amongst all objects in the collection.

Ask for the cursor as a property when iterating over a collection.

  query {
    User(login: 'jbranchaud') {
      repositories(first: 100) {
        edges {
          node {

The above query will return a cursor for each repo.

Get the last cursor of that collection with pageInfo.endCursor:

  query {
    User(login: 'jbranchaud') {
      repositories(first: 100) {
        pageInfo {
        edges {
          node {

The endCursor will look like:


Use this cursor to obtain the next 100 repos with the after property.

  query {
    User(login: 'jbranchaud') {
      repositories(first: 100, after: "Y3Vyc29yOnYyOpHOBK0NoA==") {
        pageInfo {
        edges {
          node {

Posting data from a file with curl

Iterating on an api post request with curl can be frustrating if that involves a lot of command line editing. curl however can read a file for post body contents. Generally the --data option is used like this:

curl -XPOST --data '{"data": 123}'

But when using an @ symbol you can reference a file

curl -XPOST --data @data.json

Now, you can run the same command for each iteration and edit the data.json file containing the data to be posted with your favorite text editor (which is vim right?).

ISO-8601 Formatted Dates Are Interpreted As UTC

Using new Date() or Date.parse() with a string that represents a date is a great way to create a Date object for a specified date. A variety of formats are accepted by these methods.

But, caution!

There are subtle differences in how those dates will be interpreted. Given any old string that reasonably represents a date, the date will be interpreted using the local time zone, in my case CST.

> new Date('2017-12-4')
Mon Dec 04 2017 00:00:00 GMT-0600 (CST)

However, as soon as we use an ISO-8601 compliant date format, ECMAScript 5 specifies that the date ought to be interpreted using the UTC time zone. As you can see, the results are drastic enough to affect what day it comes out to.

> new Date('2017-12-04')
Sun Dec 03 2017 18:00:00 GMT-0600 (CST)


`disable_with` to prevent double clicks

If a link or button initiates a request that takes a long time to respond then the user (being a user) might click the link or button again. Depending on the code implemented on the server this could put the application into a bad state.

Rails has a handy feature that will disable a link or button after the user has clicked it, disable_with:

<%= link_to('something',
      data: {
        disable_with: "Please wait..."

In Rails 5.0 and up sumbit buttons have disable_with set by default. To disable disable_with use:

data: { disable_with: false }

Simple text file #encryption with Vim

Vim provides a simple text file encryption feature. To make use of it add the following to your .vimrc:

set cryptmethod=blowfish2

This will set the encryption to the strongest algorithm vim supports.

Now to use it simply start editing a file with the -x flag:

$ vim -x mysecret.txt

You will be prompted for a password, and password confirmation. After that you should be able to edit the file and save it normally.

When you open the file again with vim (even without the -x flag) you will be asked to type your password to decrypt the file. If you enter the wrong password all you’ll see is gibberish.

This is not the strongest encryption out there but it works and should suffice for most personal use cases.

NOTE: this will not work with NeoVim.

Destructuring The Rest Of An Array

ES6 offers some amount of pattern matching on arrays. This means you can do fun stuff like grabbing a couple values and then destructuring the rest of the array into a variable.

> const kids = ["Mike", "Will", "Dustin", "Lucas", "Eleven", "Max"];
> const [first, second,] = kids;
> first
> second
> rest
["Dustin", "Lucas", "Eleven", "Max"]

By using the ... syntax with a variable name in the left-hand side of the assignment, you are able to capture an array of whatever isn’t assigned to preceding variables.

Hi, Sierra

I recently upgraded my Mac to High Sierra and got this gross message when I tried to use Git:

xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun

My machine was expecting Git to be implemented as an Xcode command line tool. To fix the problem, I simply installed Xcode.

xcode-select --install

Use Decorators for React Higher Order Components

When working with React libraries that make use of higher order components, you wrap your component in a function:

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

class MyComponent extends Component {

export default withRouter(MyComponent)

When chaining through multiple HOC’s, this can become unwieldly:

import { withRouter } from 'react-router-dom';
import { connect } from 'react-redux';

class MyComponent extends Component {

function mapStateToProps(state) { ... };

export default withRouter(connect(mapStateToProps)(MyComponent));

But there is hope, with the decorator syntax in ES6/Babel you can make this look a bit cleaner:

import { withRouter } from 'react-router-dom';
import { connect } from 'react-redux';

function mapStateToProps(state) { ... };

export default class MyComponent extends Component {

Full documentation here.

List all available extensions in #Postgres

Postgres comes packed with extensions just waiting to be enabled!

To see a list of those extensions:

select * from pg_available_extensions;

This will list the extension’s name, default_version, installed_version, and the comment which is a one liner description of what the extension does.

Here’s an interesting one for example:

name              | earthdistance
default_version   | 1.1
installed_version | ø
comment           | calculate great-circle distances on the surface of the Earth

To enable an extension, simply call create extension on the name:

create extension if not exists earthdistance;

whatis command and apropos in #linux #bash

Ever wonder what a command you are using is? Turns out linux has the answers for you!

Simply type whatis followed by the name of the command.


$ whatis bc
bc(1)         - An arbitrary precision calculator language
$ whatis brew
brew(1)       - The missing package manager for macOS
brew-cask(1)  - a friendly binary installer for macOS

whatis uses the man pages to search your entered query.

There is also a reverse search, which searches the descriptions of commands. For example say you are looking for a calculator:

$ apropos calculator
bc(1)         - An arbitrary precision calculator language
dc(1)         - an arbitrary precision calculator

h/t this tweet by Peter Cooper

Include Some Stats In Your Git Log

A simple git log command is going to give you a concise set of information for each commit. Usually it is enough info. When it’s not, git log can provide additional information with the right flags. To include overall and per-file stats on the number of insertions and deletions, use the --stat flag.

$ git log --stat
commit 66e67741a1cd6857a4467d1453c9f17ef5849f20
Author: jbranchaud <>
Date:   Mon Nov 13 21:24:41 2017 -0600

    Add Focus The URL Bar as an internet til                     |  3 ++-
 internet/ | 10 ++++++++++
 2 files changed, 12 insertions(+), 1 deletion(-)

commit 9241e3919ef1e4f68b71a1491d368ae6361084aa
Author: jbranchaud <>
Date:   Sat Nov 11 11:41:40 2017 -0600

    Add Freeze An Object, Sorta as a javascript til                            |  3 ++-
 javascript/ | 44 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+), 1 deletion(-)


See man git-log for more details.

Stop #bash script on error #linux #zsh

If you are writing a procedural bash script, you may want to stop execution if one of the steps errored out.

You can write error handling for each step, but that can get quite verbose and make your script hard to read, or you might even miss something.

Fortunately bash provides another option:

set -e

Simply place the above code at the top of your script and bash should halt the script in case any of them returns a non-true exit code.

Caveats: this will not work in all cases, for example it does not work for short circuited commands using &&/||.

If you want it to work when one of your operations in a pipe fails you will need to add the pipefail flag (not supported on some systems set -o | grep pipefail to check your system):

set -e -o pipefail

If you have a script that always returns a non true return code and that’s fine you can override set -e for that command with:

set +e
set -e

At this point I consider it a best practice to include this statement in every script I write.

Partial post body matching with webmock

When using webmock to stub out a post, you can specify that the post has a specific body. When dealing with web apis, that body is json and you want to compare the body to a ruby hash, from the webmock README, that looks like this:

stub_request(:post, "").
  with(body: {a: '1', b: 'five'})

In the above example, the whole json body has to be represented in the hash. Webmock provides a way to just examine a portion of the json/hash with the hash_including method. This is not the rspec hash_including this is a webmock specific function using the WebMock::Matchers::HashIncludingMatcher class.

stub_request(:post, "").
  with(body: hash_including({a: '1'}))

The rest of keyword arguments 🍕

Sometimes you pass some extra keyword arguments to a method that doesn’t handle them and you get the error ArgumentError: unknown keywords: ....

You can just use ** as the last argument to ignore the rest of the keyword arguments:

def make_pizza(cheese:, sauce:, **)
  puts "Making pizza with #{cheese} cheese and #{sauce} sauce"

make_pizza(cheese: 'muzzarella', sauce: 'tomato', chocolate: 'white', syrup: 'mapple')

=> Making pizza with muzzarella cheese and tomato sauce

You can also give it a name to group them:

def make_pizza(cheese:, sauce:, **rest)
  puts "Making pizza with #{cheese} cheese and #{sauce} sauce"
  rest.each {|k, v| puts "#{v.capitalize} #{k} is not good for you"}

make_pizza(cheese: 'muzzarella', sauce: 'tomato', chocolate: 'white', syrup: 'mapple')

=> Making pizza with muzzarella cheese and tomato sauce
=> White chocolate is not good for you
=> Mapple syrup is not good for you

Toggle Mirror Display (OSX)

When using a separate display like a projector, I often switch between screen mirroring (my screen matches the secondary display screen) and not mirroring. Especially during a presentation that uses both slides and live-coding in the terminal.

Instead of navigating through ‘System Preferences’ > ‘Displays’ > ‘Arrangement’, and checking or unchecking the ‘Mirror Displays’ checkbox, I can toggle between the two with ⌘ + F1.

List filenames of multiple filetypes in project

Ag (aka The Silver Searcher) is an amazing piece of software. It allows you to define file types (like Ack) and comes prepackeged with some file types.

Using this feature you can list all files of a specific type in your project. For example say we want to list all Ruby and JavaScript files:

ag --ruby --js -l

Ag has the added benefit over Ack, that it ignores gitignored files, so you only get the files that matter (and not stuff from node_modules etc).

To see what filetypes Ag supports:

ag --list-file-types

The list is pretty extensive! Unlike Ack however, there is currently no way to add new file types or extend the list.

Using ngrok to evaluate webhhooks in a dev env

A webhook, an http request to a server initiated by an outside service, is difficult to test. The outside service must have a valid url to make the request with, but your development server generally runs on the unreachable localhost.

The Ngrok product page describes ngrok like this:

It connects to the ngrok cloud service which accepts traffic on a public address and relays that traffic through to the ngrok process running on your machine and then on to the local address you specified.

If I have a local dev server on port 3000 I run ngrok like so:

> ngrok http 3000
Forwarding -> localhost:80

Then, configure the outside service to point the webhook at the address provided by the ngrok tool. Now, your local server will receive http requests from the outside service and you can evaluate those requests effectively.

Focus The URL Bar

There are a lot of things you can do in the browser without having to reach for the mouse. Bringing the URL bar into focus is one of those things.

Hit Cmd+L in any modern browser (I’ve tried Chrome, Firefox, and Safari) and the URL bar will be brought into focus. From there, you can quickly change the URL of the current tab and your fingers never left the keyboard.

h/t Jake Worth

Alternate names in destructuring assignment

Want to use destructuring assignment, but don’t like the names of the variables as they exist in the object?

If you have data like this:

const optimus = { name: 'Optimus', type: 'Semi-Truck' };
const bumblebee = { name: 'Bumblebee', type: 'Small Car' };

Instead of creating customized variables like this:

const { name, type } = bumblebee;
const bumblebeeName = name;
const bumblebeeType = type;

You can express this type of destructuring in one line like:

const { name: optimusName, type: optimusType } = optimus;

Freeze An Object, Sorta

You can freeze a JavaScript object using Object.freeze which will help enforce some immutability practices. Don’t be fooled though, you can still modify arrays and objects in the frozen object.

Here is what the docs have to say:

The Object.freeze() method freezes an object: that is, prevents new properties from being added to it; prevents existing properties from being removed; and prevents existing properties, or their enumerability, configurability, or writability, from being changed, it also prevents the prototype from being changed.

And here is Object.freeze in action:

> const things = {one: "two", hello: "world", cats: ["Von Neumann", "Sosa"]}
> Object.freeze(things)
{one: "two", hello: "world", cats: Array(2)}

> = "three"
> things.dogs = []
> delete things.hello

> things
{one: "two", hello: "world", cats: Array(2)}

> things.cats.push("Sneaky")

> things
{one: "two", hello: "world", cats: Array(3)}

See the MDN Docs for more details.

h/t Jake Worth