Skip to main content

Multiple Instruction Arrow Functions in ES6

Cross post from my employer's development blog: http://rootinc.github.io/2016/02/05/multi-inst-arrow-es6/

Recently, I had a bit of JavaScript code that was a small series of map and reduce functions. To keep things nice and tight, I of course wanted to use single line arrow functions as much as possible. Implicit returns, no brackets, no ‘function’ syntax. I had one reduce() call though where my logic was this:

arr.reduce((list2, b) => {
         if (list2.indexOf(b) === -1){
           list2.push(b);
         }
         return list2;
       }, []);

High level: only add item b from array arr to a new array if it doesn’t already exist in the new array. Simple duplicate removal for the original array. This works, and is probably the easiest to understand, but doesn’t make for the best grouping along with other calls on the same array. How could I modify this a bit so that I could use a bracketless arrow function with an implicit return?

arr.reduce((list2, b) =>
         ((list2.indexOf(b) === -1 && list2.push(b)) || 1) && list2
       , []);

This is certainly shorter in terms of vertical space, and a bit less code overall. However, it’s not very straight-forward to read. The logical AND operator ensures push() is only called on list2 if the item ‘b’ is not found in list2. In the case that ‘b’ is indeed in list2, the value’s index will not be -1 and the AND expression will short circuit and return false. Which would return false for the whole function, which we don’t want. So, I use the logical OR operator and 1 to ensure we get a truthy return value and then another AND to force list2 to be returned.

During all this, I was reminded of part of the JS spec about the comma operator. According to [MDN][comma]:

“The comma operator evaluates each of its operands (from left to right) and returns the value of the last operand.”

Nice! We can simplify this even more:

arr.reduce((list2, b) =>
         (list2.indexOf(b) === -1 && list2.push(b), list2)
       , []);

Which transpiles in ES5 to:

arr.reduce(function (list2, b) {
         return list2.indexOf(b) === -1 && list2.push(b), list2;
}, []);

We’ve removed two of the three logical operators and one of the parens wrappings. Overall, I’d say it’s cleaner than the 2nd iteration and preferable to it as well. However, the use of the comma operator like this is probably not immediately known to the random developer reading the code. Thus I’m a tad hesitant moving forward with it and may go with the more verbose, but easier to understand, bracketed arrow function. Neat trick though, especially as you can chain more commas and expressions to your heart’s desire.

[comma]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator

Comments

Popular posts from this blog

Fancy FTP Deployment with Grunt

I recently dove into Grunt.js at work for automating our build process and I haven’t looked back. It’s an awesome tool with a plug-in for just about anything. I expected the usual would be there like JavaScript minification and concatenation, but I was surprised at a few others that I found, one being for FTP file deployment. Just shows how popular and community supported Grunt is.

There are a few FTP plug-ins available for Grunt. I didn’t do an analysis of all of them but ran across grunt-ftp-push which seemed to do what I needed so I decided to try it out. A simple ftp-push setup to upload an entire project via FTP could look like this:

grunt.initConfig({ftp_push:{all:{options:{host:'example.com',port:21,dest:'/project/path/',username:'user',password:'pass'},expand:true,cwd:'dist',src:['**/*','!**/*.zip']}}});
Some details here: I opted to put the username and password in the main config rather than using an .ftpauth file. The …

Accessing other HTTP servers on Cloud 9 IDE

If you're using Cloud 9 to do development, you'll quickly realize that only ports 8080 through 8082 are available to the outside world from your development box. This is generally not an issue as you can set your application to bind to the $PORT environment variable when in development mode. However, there are sometimes other servers that we want to make use of that host on different default ports.

I recently had to setup a Neo4j server which defaults the admin interface of port 7474. Unfortunately, I could not access the admin interface even through the IDE based web browser window. So, what to do? I could change the default server settings so that it runs on a different port. However, the app I'm working on with a team has 7474 hard-coded and I currently don't feel like writing a local only work-around.

After some searching, I ran across a neat Linux tool called socat. This allows us to easily forward one port to another. After a quick install via apt-get, I ran the …

Moving to Babel 6 on the Server

Cross post from my employer's development blog: http://rootinc.github.io/2016/03/14/babel-6-server/

Decided it was time to upgrade my server-side code to run on Babel 6. Below is a synopsis of all the issues I ran into and resolved while upgrading my 0.11.3 SailsJS server to run with Babel 6 transpilation.

The upgrade to Babel 6 itself is easily achieved in Sails by upgrading the `sails-hook-babel` package.

### Missing preset
`couldn't find preset "stage-0" relative to directory`
Just because a preset is on the official Babel preset page, doesn’t mean that Babel comes with it. Simple fix by installing the [package][1] from npm. Read more [here][2].
[1]: https://www.npmjs.com/package/babel-preset-stage-0
[2]: http://jamesknelson.com/the-six-things-you-need-to-know-about-babel-6/

### Need strict mode everywhere
`Block-scoped declarations (let, const, function, class) not yet supported outside strict mode`
I didn’t have to worry about this before, and I don’t feel like …