When you should not use JavaScript fat arrow functions


Code readability is extremely important. By some estimates, we’ll spend significantly more of our time as developers reading and mentally parsing code rather than writing it. Arrow functions can both improve and hurt readability. It is very important that we make choices that optimize our code for readability. I’m going to assume for the sake of this article is that the readers are using some form of JavaScript modules with a single module per file. The goal of the module, when it comes to readability, is to make it easy for a person to understand what that particular module does, and the interface it provides for use in other modules.

In JavaScript, ES2015 (i.e. ES6) introduced the fat arrow function syntax, and it is great … for some use cases. But I keep seeing developers recommending and using arrow function assignment to a const variable as a substitute for using function declaration. I think that is a problem and contributes to poor readability in most JavaScript files that use that pattern.

Let’s back up a bit and define some of these terms, and then we can talk about arrow functions, where they are great and where traditional functions can be used to improve readability.

 

Function Declaration

Using the function keyword to declare a function. Functions declared in this manner get their own scope (and also close over the enclosing scope). They will be hoisted to the top of their containing scope. Unlike variables declared with var that get hoisted though, functions declared and hoisted in this manner are callable immediately, regardless of where they are declared in the code scope.

function myFunc() {}

 

Function Expression

Using an assignment to assign an anonymous or arrow function to a variable. We used const here to ensure the variable cannot be re-assigned. The two statements are different, mainly in how they treat the this keyword.

const myFunc1 = function() {}
// or
const myFunc2 = () => {}

 

Arrow Functions

Arrow functions can be awesome. And assigning it with the const keyword does provide a benefit that means the function cannot be redeclared or overwritten. One of the best uses for arrow functions is in simple callback methods, like map, sort, and reduce. My personal rule of thumb is to move to a declared function once an arrow function exceeds 2 lines, although individual circumstances can warrant exceptions.

const doubledArray = originalArray.map((arrItem) => arrItem * 2);

But, when arrow functions start to extend to multiple lines, they can start to create problems when it comes to the readability of the code in my opinion. An assignment via const must come before those variables can be used in a module. Some of you may see where we’re going here.

 

The Problem

The main core of JavaScript modules can often be pushed down out of sight by the const assignments that must be done prior to being able to be used.

const _utility1 = () => {
  // multiple lines of code here
};
const _utility2 = () => {
  // multiple lines of code here
};
const action1 = () => {
  // multiple lines of code here, which use _utility1() and _utility2()
};

export { action1 }

If the example above, the interface for this module is via the action1 function, which uses the 2 utility functions. Because they are being assigned to const variables, they need to be declared prior to exporting them for use outside the module. The important information for someone reading this module isn’t the implementation of the utility1 or utility2, and they likely don’t even need to know about the specific implementation of the action1 function. They need to know that they can use action1 outside of this module.

 

Using function declarations (and good names) to solve the problem

A fairly simple rewrite to take advantage of function hoisting, along with high quality names, can make the file much more scannable and ensuring that a developer reading the code gets the information they need without having to read any extraneous code first. They can always dive into the individual functions as needed, but when opening the file for the first time, it is very clear what is going on.

export { wellNamedFn }

function wellNamedFn() {
  // multiple lines of code here, which use _utility1() and _utility2()
}
function _utility1() {
  // multiple lines of code here
}
function _utility2() {
  // multiple lines of code here
}

By utilizing the function hoisting feature of JavaScript, the isolation that modules provide (meaning there is not a concern that the function would get redefined),  the code can be arranged so that the most important information is front and center when a developer opens the file to read the code.

I’ll leave off with a hello world example, a React Component that has a utility function (often many utility functions) before the render function.

class HelloWorld extends React.Component {
const getGreetingSubject = () => 'world';

render() {
return <h1>Hello {getGreetingSubject()}!</h1>
}
}

vs

class HelloWorld extends React.Component { 
render() {
return <h1>Hello {getGreetingSubject()}!</h1>
}
}

function getGreetingSubject() {
return 'world';
}

It may seem relatively contrived in these small examples, but in real world cases, the irrelevant code can be significant and cause readability issues. By considering what is most important in each module, high readability can be ensured by focusing on making those important pieces of code very clear.

EmberJS 2018: Dogfooding Ember on Emberjs.com


I started using Ember about 18 months ago. In that time I’ve come to learn the ins and outs, the good parts, and the frustrating parts, that make up Ember. I’ve wanted to give back to the framework that I was using, and I have made some minor fixes to some of the addons in the ecosystem, and just recently (yesterday) got a PR merged to fix an issue with the Ember Guides. But I get ahead of myself – I struggled to jump in and contribute to Ember itself. When there was a call for blog posts about the future of Ember in 2018, I knew what I wanted to speak about my experience and provide some motivation for the Ember community and team members to dogfood our own product to make marketing Ember better and to help make contributing simpler. From a technical point of view, I believe Ember is one of the top frameworks already, and it’s a shame more people don’t know that.

What is Dogfooding? – Its a term used to describe an organization using its own product.
The idea is that if the organization truly believes its own product to be superior, it would use the product itself.

Marketing Ember

I did a little competitive analysis when writing this post. Of all of the major frameworks I looked up, Ember was the only one that didn’t dogfood their framework for the main website. React, Angular, AngularJS, Vue…Knockout, Polymer, Meteor – I looked up quite a few of the common front end Javascript frameworks new and old, and every single one of the sites I looked at used their framework to build their site – except for Ember.

I know there are historical reasons for this. Well, I don’t think they hold water anymore. This year, 2018, Emberjs.com needs to be built with Ember. Other people have written in their posts about the need for better marketing of Ember. But all of that marketing falls flat if, when a prospective dev comes to the Ember website, and opens Wappalyzer, inspects the source code, or looks on Github and finds that it isn’t Ember. They don’t know any of the reasons for it. They just know that the people that build Ember don’t use it on their website. And that can put a seed of doubt in their mind. Maybe enough to move on to another framework.

New Contributors

The other aspect of this is the loss of potential contributors.

When I looked into what I could contribute to Ember, I gravitated toward helping the Learning Team with work on the emberjs.com website. So I went to the EmberJS repo on Github, found the Website Source, and started looking at the issues – found one or two I thought I could help with. I cloned the project, and tried to get it to run and was perplexed. My expectation was an Ember app, and instead I found a Ruby and Middleman website. When trying to get that running locally I found that there were known bugs running it on Windows, my main development environment at home. I did reach out on the Ember Slack and a few people tried to help me get things running to no avail. And I let it lay there for a bit, got busy at work and other side projects, and at that point, Ember had lost a potential contributor. I didn’t even know there were other apps that made up the website, so that was it at that time.

Ember is used by developers who tend to be focused on the front end ecosystem. And while there are plenty of front end devs who are great at Ruby and Middleman, that isn’t going to be the norm. And frameworks need new blood on the team. They need the enthusiasm people new to helping out of the framework can bring. The new ideas that come with those people. So let’s make it easier to do so, by ensuring Emberjs.com is built in the framework they likely use every day. Or at the simplest, in the languages they use every day (HTML/CSS/JS).

As a front end framework, obviously there needs to be some dev-ops and backend APIs for the website to work. But I’d argue that the Emberjs.com website is THE place for Ember to shine. If it can be done in Ember, it should be done in Ember. I envision the website repo on github as one of the places to go to see how to use Ember in practice.

Call to Arms

There are a number of benefits that come with dogfooding Ember:

  • Greater awareness of rough areas and earlier problem detection
  • More accurate marketing message around exactly what benefits Ember provides
  • Higher level of confidence from those evaluating Ember and for those using it
  • Boost to morale in the community to see Ember being used and promoted by the core team

There are already pieces of the site built with Ember. The Learning Team is actively working to transition more parts to Ember, just launching the recently Emberized Guides app a few days ago. This is not a critique of those efforts, but rather to encourage the effort of Emberizing the website to continue, and to set forth the goal of having the entire Ember website made from Ember this year, in 2018. And I encourage anyone reading who has interest in assisting in that effort to join me in asking what we can do to help.

iOS UIView, WebApps and iFrames


One of our existing responsive websites (built using Angular) was being pulled in as part a Cordova project to make an iOS and Android app, and the developers had some weird issues on iOS. Inside the Cordova app, our app was loaded in an iframe. I wanted to write about a few of the issues that came up, particularly with the iOS UIView, and some of the hackery I resorted to in order to resolve the issues.

Issue 1: Fun with iOS Iframes

First issue we had was that the app kept bouncing between the small and xlarge media query. This turned out to be due to what I consider a bug in iOS, in that iframes size to their content, rather than sizing based on the attributes/styles on the iframe itself or parent constraints. We had logic that enabled some functionality on small, which in turned created a wide html element for a carousel and due to the iframe bug in iOS, would cause the width of the iframe to grow to the xlarge size again. The carousel functionality would be destroyed, as it was only for small, causing the element that was created to hold the slides to be destroyed, causing the iframe to shrink back down to the small size again. And then the cycle would repeat, infinitely.

I was able to fix this issue by immediately setting an explicit width on the body before any of the rest of the HTML was loaded/parsed. This worked in our case because the application will always be in portrait mode, we would need to also watch for resize events and things would get more complicated. Right at the top of the body, I added the following code:

<script>
  document.body.style.width = document.body.clientWidth + 'px';
</script>

Issue 2: iOS WebApp links open in Mobile Safari

The second issue we had was that any link clicked in the website being wrapped in this iframe would load in Safari. It didn’t matter if the link was relative or fully qualified, or what kind of target (or lack thereof) it had. Turns out that is normal behavior for web apps on iOS. I’m not proud of the solution, but the fix was to grab all links in the app, watch the click event, stop the default browser action, and load the new page with window.location. It looked something like this:

$('html').on('click', 'a', function (event) {
  var href = $(this).attr('href');
  if(href && href.indexOf('http') !== -1 && !event.defaultPrevented) {
    event.preventDefault();
    document.location.href = href;
  }
});

I had jQuery available, but for a non-jQuery version, check this out here: https://gist.github.com/kylebarrow/1042026

My initial solution broke links in the site that already had JavaScript functionality attached to them, so the click event was delayed briefly from being attached by wrapping it in a timeout. That way it should be the last event attached, and be skipped if the event had already had preventDefault called on it.

Overall, it’s two hacks that fixed the issues we were seeing. Mileage may definitely vary given, but hopefully this will prove useful to the reader (or more likely, a future me trying to figure this out again).

Vanilla JavaScript vs. Framework Functions


Had a quick conversation at work today about whether or not it was good to use built-in framework functions for tasks that are simple to write in vanilla JavaScript. For example:

angular.isFunction(fn) 

vs

typeof fn === 'function'

I’ve tended to do the vanilla JavaScript, but while checking if something is a function is almost identical in complexity/length, while others can be (slightly) more complex:

angular.isObject(yourVariable) 

vs. 

yourVariable !== null && typeof yourVariable === 'object'

Still, either way is pretty readable, and fairly clear what it is doing. I wonder if this is what leads to people bashing frameworks like Angular for teaching people the “framework” rather than vanilla JavaScript, as newer coders who may not have ever had to check variable types who are learning Angular may use the framework checks without knowing how to do a similar thing in vanilla JavaScript.

I like to collect snippets that will help me, and reuse them where appropriate. This probably tends to skew me towards vanilla JavaScript, because I want my snippets to work no matter what project I am working on. For example, the following snippet gets the class (or type) of a JavaScript variable.

/**
 * getClass - get real type of JavaScript object 
 * @param object
 * @returns {string}
 */
function getClass(object) {
    return Object.prototype.toString.call(object).slice(8, -1).toLowerCase();
}

/*
getClass({}) // "object"
getClass([]) // "array"
getClass(function(){}) // "function"
getClass('') // "string"
getClass(1) // "number"
*/

I came away from the conversation thinking there was not one right way. If you are writing an app with the help of of a framework, there is nothing wrong with using the tools the framework provides. At the same time, it shouldn’t become a crutch where a framework is needed because a developer isn’t comfortable doing the same thing in vanilla JavaScript.

Support Net Neutrality, tell the FCC!


PSA: Less than 14 hours to go. That’s how long we have to get pro-Net Neutrality comments submitted to the FCC in front of their first comment period deadline (midnight Tuesday) — and save the Internet from the clutches of Comcast, Time Warner, and their ilk.

This website makes it very easy to send the FCC a formal comment demanding support for Net Neutrality. It’ll only take a minute, although if you customize the message it may have even more impact.

https://www.battleforthenet.com/