💾 Archived View for gemini.njms.ca › gemlog › modern-js-arrow-functions.gmi captured on 2024-12-17 at 09:36:19. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2024-05-10)
-=-=-=-=-=-=-
In the past, we would see a lot of this:
someFunction(param, function() { // do something });
Now, this gets a little bit cumbersome after a while. Not only are function expressions long, they include a kitchen sink of features that you probably won't need in all cases, like the `this` or a `new` constructor.
Thankfully, in EMCAScript 6, we got this whole new and improved arrow function. Let's take a look.
The declaration of an arrow function goes like this:
(param1, param2 ... paramN) => expression
Arrow functions may remind you of the lambda or anonymous function syntax used various other programming languages like Haskell:
someFunction(param, () => { // do something });
As you can see, they're defined with the parameters wrapped in brackets, followed by an `=>` arrow and an expression. If your arrow function doesn't need any parameters, you can just use two empty brackets as I did above. Here's another example:
var array = [1, 2, 3, 4]; var increment = 2; var incremented = array.map(item => item + increment); // [3, 4, 5, 6]
When writing arrow functions like this (without using `{}` curly braces), you don't even need to use the `return` keyword, similar to how you would return a value in a language like Rust. It's implied that, since there's only one expression that needs to be evaluated, it should be returned.
In that example, we didn't use brackets around the argument `param`. When you only have one parameter, brackets are optional.
One of the things that makes arrow functions so useful is that they don't have their own `this` object. Consider the following:
var object = { values: [2, 4, 6, 8], multiplyBy: 7, multiply() { // ES6 also let's us write functions in objects like this return this.values.map(function (value) { return value * this.multiplyBy; }) } }
However, if we try to run this, we'll get an `Array [ NaN, NaN, NaN, NaN ]` value. Why, you ask? Try taking a closer look at that anonymous function.
As I explained in my article on closures, Every nested function takes on the *lexical scope* of the function it's nested in. In other words, all values made available in the outer function exist in the inner function. For this reason, we might expect that the `this` object should be available as well. However, the anonymous function you're working in already has it's own `this` which takes superiority.
[Closures in programming: What are they and how do they work?](/posts/closures-in-programming.html)
Though we might have access to `multiplyBy` in the outer function, getting to it within the inner function is a bit more difficult. Before ES6, people often used this hack:
var self = this; return this.values.map(function (value) { return value * self.multiplyBy; })
Sure, this works, but it's a bit of a compromise. Thankfully, arrow functions solve this issue beautifully.
var object = { values: [2, 4, 6, 8], multiplyBy: 7, multiply() { return this.values.map(value => value * this.multiplyBy); } }
Since arrow functions don't have `this`, no referencing is required to access the `multiplyBy` value.
Perfect.
Let's take a look at this function I wrote to simplify the process of querying an API with an AJAX call using jQuery:
function queryAPI(query, datatype, callback) { return $.ajax({ url: query, dataType: datatype, success: callback.success, error: callback.error }); }
The function takes three parameters: the complete URL, the data type and a success and error callback wrapped in an object. We can call this function like so:
queryAPI("https://api.example.com/some/query", "json", { success: function(data) { element.innerHTML = data; }, error: function(error) { element.innerHTML = error; } })
Now that we know more about arrow functions, things would look a lot nicer written like this:
queryAPI("https://api.example.com/some/query", "json", { success: data => element.innerHTML = data, error: error => element.innerHTML = error })
EMCAScript 6 is full of great features. Sure, many of them might not be supported natively in all browsers yet, but that doesn't mean it's too early to start!
[Arrow functions (developer.mozilla.org)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)
[ES6 In Depth: Arrow functions](https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/)
[Arrow function vs function declaration / expressions: Are they equivalent / exchangeable?](https://stackoverflow.com/questions/34361379/arrow-function-vs-function-declaration-expressions-are-they-equivalent-exch)
*Agree or disagree? Think I missed or poorly explained something important? Questions, comments or concerns? Leave a comment down below!*
---
"Modern JS concepts: Arrow functions, the new and improved function literals" was published on 2017-12-28
If you have thoughts you'd like to share, send me an email!