Table of Contents
-
- About The Author
- About the Technical Reviewers
-
Prelude
- A Story About Why I Wrote This Book
- Why Should You Care About JavaScript?
- What is the Goal of This Book?
- What is the Goal of The JavaScript-mancy Series?
- Why JavaScript-mancy?
- Is This Book For You?
- How is The Book Organized?
- How Are The JavaScript-mancy Series Organized? What is There in the Rest of the Books?
- Understanding the Code Samples in This Book
- A Note About ECMAScript 5 and ECMAScript 6,7 within The Book
- A Note About the Use of Generalizations in This Book
- Do You Have Any Feedback? Found Any Error?
- A Final Word From the Author
-
Tome I. Mastering the Arcane Art of JavaScript-mancy
- Introduction
- Once Upon a Time…
-
The Essential Ingredients Of JavaScript-Mancy
- An Introduction to JavaScript-Mancy
- JavaScript
- JavaScript Has Some Types
- Strings in JavaScript
- Functions in JavaScript
- OOP and Objects in JavaScript
- Arrays, Maps and Sets in JavaScript
- JavaScript Flow Control
- Logical Operators in JavaScript
- Exception Handling
- Regular Expressions
- But Beware, JavaScript Can Be Weird and Dangerous
- Concluding
- The Basics Of JavaScript Functions
- Useful Function Patterns: Default Arguments
- More Useful Function Patterns: Arbitrary Arguments
- More Useful Function Patterns: Function Overloading
- On the Art of Summoning Servants and Critters, Or Understanding The Basics of JavaScript Objects
- Mysteries of the JavaScript Arcana: JavaScript Quirks Demystified
- A Guide to Strings, Finding the Right Words and Proper Spell Intonation
- Upgrading Your Everyday JavaScript Magic With ES6 - Destructuring
- Upgrading Your Everyday JavaScript Magic With ES6 - Arrow Functions
- Upgrading Your Everyday JavaScript Magic With ES6 - The Spread Operator
- Tome I.II JavaScriptmancy and Data Structures
- Book I. Epilogue
- Tome I.III JavaScriptmancy and OOP: The Path of The Summoner (preview)
- References and Appendix
- Notes
About The Author
Jaime González García (@Vintharas) Software Developer and UX guy, speaker, author & nerd
Jaime is a full stack web developer and UX designer who thinks it’s weird to write about himself in the third person. During the past few years of his career he has been slowly but surely specializing in front-end development and user experience, and somewhere and some time along the way he fell in love with JavaScript. He still enjoys developing in the full stack though, bringing ideas to life, building things from nothingness, beautiful things that are a pleasure and a delight to use.
Jaime works as a Technical Solutions Consultant at Google helping publishers be great. He also builds his own products in his spare time and blogs at barbarianmeetscoding.com (long story that one). He loves spending time with his beloved Malin, drawing, writing, reading fantasy and sci-fi, and lifting heavy weights
About the Technical Reviewers
Nathan Gloyn (@NathanGloyn) Passionate developer, architect and speaker
Independent software consultant and agile coach, Nathan is passionate about development and a firm believer in agile principles. In his day job he is contractor helping clients to build and deliver working software.
Nathan has successfully bootstrapped agile teams in various companies and has given presentations on technology and agile at a number of events.
Andreas Bäcklund (@andbackl) Consultant, passionate programmer
Andreas is a consultant, passionate programmer, double master and a lifelong learner.
Andreas enjoys all sorts of tech and has been developing software that runs on everything from ship engines to the cloud. He enjoys working in the full stack because it’s rewarding, exciting and challenging, all at the same time.
Prelude
It was during the second age that the great founder of our order Branden Iech, first stumbled upon the arcane REPL, and learnt how to bend the fabric of existence to his very will, then was that he discovered there was a mechanism to alter the threads being weaven into the Pattern, then that we started experiencing the magic of JavaScript - Irec Oliett, The Origins of JavaScript-Mancy Guardian of Chronicles, 7th Age
Imagine… imagine you lived in a world were you could use JavaScript to change the universe around you, to tamper with the threads that compose reality and do anything that you can imagine. Well, welcome to the world of JavaScript-mancy, where wizards, also known as JavaScriptmancers, control the arcane winds of magic wielding JavaScript to and fro and command the very fabric of reality.
We, programmers, sadly do not live in such a world. But we do have a measure of magic 1 in us, we have the skills and power to create things out of nothingness. And even if we cannot throw fireballs or levitate (yet), we can definitely change/improve/enhance reality and the universe around us with our little creations. Ain’t that freaking awesome?
Well, I hope this book inspires you to continue creating, and using this beautiful skill we share, this time, with JavaScript.
A Story About Why I Wrote This Book
I was sitting at the back of the room, with my back straight and fidgetting with my fingers on the table. I was both excited and nervous. It was the first time I had ventured myself to attend to one of the unfrequent meetings of my local .NET user group. Excited because it was beyond awesome to be in the presence of so many like-minded individuals, people who loved to code like me, people who were so passionate about software development that were willing to sacrifice their free time to meet and talk about programming. Nervous because, of course, I did not want to look nor sound stupid in such a distinguished group of people.
The meetup started discussing TypeScript the new superset of JavaScript that promised Nirvana for C# developers in this new world of super interactive web applications. TypeScript here, TypeScript there because writing JavaScript sucked… JavaScript was the worst… everybody in the room started sharing their old war stories about writing JavaScript, how bad it was in comparison to C#, and so on…
“Errr… the TypeScript compiler writes beautiful JavaScript” I adventured to say… the room fell silent. People looking astonishingly at each other, uncomprehending, unbelieving… Someone had dared use beautiful and JavaScript in the same sentence.
This was not the first, nor will be the last time I have encountered such a reaction and feelings towards JavaScript as predominant in the .NET community. JavaScript is not worthy of our consideration. JavaScript is a toy language. JavaScript is unreliable and behaves in weird and unexpected ways. JavaScript developers don’t know how to program. JavaScript tooling is horrible…
And every single time I sat muted, thinking to myself, reflecting, racking my brains pondering… How to show and explain that JavaScript is actually awesome? How to share that it is a beautiful language? A rich language that is super fun to write? That’s how this book came about.
And let me tell you one little secret. Just some few years ago I felt exactly the same way about JavaScript. And then, all of the sudden, I started using it, with the mind of a beginner, without prejudices, without disdain. It was hard at first, being so fluent in C# I couldn’t wrap my head around how to achieve the same degree of fluency and expressiveness in JavaScript. Nonetheless I continued forward, and all of the sudden I came to love it.
The problem with JavaScript is that it looks too much like C#, enough to make you confident that you know JavaScript because you know C#. And just when you are all comfortable, trusting and unsuspecting JavaScript smacks you right in the face with a battle hammer, because, in many respects, JavaScript is not at all like C#. It just looks like it on the surface.
JavaScript is indeed a beautiful language, a little rough on the edges, but a beautiful language nonetheless. Trust me. You’re in for a treat.
Why Should You Care About JavaScript?
You may be wondering why you need to know JavaScript if you already grok C#.
Well, first and foremost, JavaScript is super fun to write. Its lack of ceremony and super fast feedback cycles make it a fun language to program in and ideal for quick prototyping, quick testing of things, tinkering, building stuff and getting results fast. If you haven’t been feeling it for programming lately, JavaScript will help you rediscover your passion and love for programming.
JavaScript is the language of the web, if you are doing any sort of web development, you need to understand how to write great JavaScript code and how JavaScript itself works. Even if you are writing a transpiled language like TypeScript or CoffeeScript, they both become JavaScript in the browser and thus knowing JavaScript will make you way more effective.
But JavaScript is not limited to the web, during the past few years JavaScript has taken the world by storm, you can write JavaScript to make websites, in the backend, to build mobile applications, games and even to control robots and IoT devices, which makes it a true cross-platform language.
JavaScript is a very approachable language, a forgiving one, easy to learn but hard to master. It is minimalistic in its contructs, beautiful, expressive and supports many programming paradigms. If you reflect about JavaScript features you’ll see how it is built with simplicity in mind. Ideas such as type coercion (are “44” and 44 so different after all?) or being able to declare strings with either single or double quotes are great expressions of that principle.
JavaScript’s openness and easy extensibility are the perfect foundations to make it a fast-evolving language and ecosystem. As the one language for the web, the language that browsers can understand, it has become the perfect medium for cross-pollination across all software development communities, where .NET developers ideas can meet and intermingle with others from the Ruby and Python communities. This makes knowledge, patterns and ideas spread accross boundaries like never before.
Since no one single entity really controls JavaScript2, the community has a great influence in how the language evolves. With a thriving open source community, and openness and extensibility built within the language, it is the community and the browsers the ones that develop the language and the platform, and the standard bodies the ones that follow and stabilize the trends. When people find JavaScript lacking in some regard, they soon rush to fill in the gap with powerful libraries, tooling and techniques.
But don’t just take my word for it. This is what the book is for, to show you.
What is the Goal of This Book?
This book is the first installment of the JavaScript-mancy series and its goal is to provide a great and smooth introduction to JavaScript for C# developers. If you are a C# developer that has had no or little experience with JavaScript before then this book will help you get started. If you have had quite a bit of experience with JavaScript but it is still frustrating and you don’t understand why things behave the way they do, then this book will boost your JavaScript Fu until you start enjoying the language.
What is the Goal of The JavaScript-mancy Series?
The goal of the JavaScript-mancy series is to make you fluent in JavaScript, able to express your ideas instantly and build awesome things with it. You’ll not only learn the language itself but how to write idiomatic JavaScript. You’ll learn both the most common patterns and idioms used in JavaScript today, and also all about the latest version of JavaScript: ECMAScript 6 (also known ECMAScript 2015) and even about the upcoming version ECMAScript 7.
But we will not stop there because what is a language by itself if you cannot build anything with it. I want to teach you everything you need to be successful and have fun writing JavaScript after you read this series. And that’s why we will take one step further and take a glance at the JavaScript ecosystem, the JavaScript community, the rapid prototyping tools, the great tooling involved in building modern JavaScript applications, JavaScript testing and building an app in a modern JavaScript framework: Angular 2.
Why JavaScript-mancy?
Writing code is one of my favorite past times and so is reading fantasy books. For this project I wanted to mix these two passions of mine and try to make something awesome out of it.
In fantasy we usually have the idea of magic, usually very powerful, very obscure and only at the reach of a few dedicated individuals. There’s also different schools or types of magic: pyromancy deals with fire magic, allomancy relates to magic triggered by metals, necromancy is all about death magic, raising armies of skeletons and zombies, immortality, etc.
I thought that drawing a parallel between magic and what we programmers do daily would be perfect. Because it is obscure to the untrained mind and requires a lot of work and study to get into, and because we have the power to create things out of nothing.
And therefore, JavaScript-mancy, the arcane art of writing awesome JavaScript.
Is This Book For You?
I have written this book for you C# developer:
- you that hear about the awesome stuff that is happening in the realm of JavaScript and are curious about it. You who would like to be a part of it, a part of this fast evolving, open and thriving community.
- you that have written JavaScript before, perhaps even do it daily and have been frustrated by it, by not been able to express your ideas in JavaScript, by not being able to get a program do what you wanted it to do, or struggling to do so. After reading this book you’ll be able to write JavaScript as naturally as you write C#.
- you that think JavaScript a toy language, a language not capable of doing real software development. You’ll come to see an expressive and powerful multiparadigm language suitable for a multitude of scenarios and platforms.
This book is specifically for C# developers because it uses a lot of analogies from the .NET world, C# and static typed languages to teach JavaScript. As a C# developer myself, I understand where the pain points lie and where we struggle the most when trying to learn JavaScript and will use analogies as a bridge between languages. Once you get a basic understanding and fluency in JavaScript I’ll expand into JavaScript specific patterns and constructs that are less common in C# and that will blow your mind.
How is The Book Organized?
This is the introductory book to Part I. Mastering the Art of JavaScript-mancy which aims to teach you how to write JavaScript with fluency.
We will start by taking a quick walkthrough through all that JavaScript has to offer from types, functions and objects, to data structures, exception handling and regular expressions.
Then we will do a deep dive into JavaScript functions which are more common-place and live more independent lives in JavaScript than in C#. You’ll learn different patterns to do defaults, multiple arguments, function overloading in both ES5 and ES6.
We will continue taking a look at objects in JavaScript and at the many improvements that ES6 brings to object literals.
After you’ve learned more about functions and objects, two core constructs of JavaScript, we will discuss the big gotchas where we C# developers usually get stuck and stumble focusing particularly in the behavior of the this
keyword.
We will finish this introduction to JavaScript with a look at some great ES6 features that will improve the readability of your code and at JavaScript data structures: the super useful and polifacetic array, the map and the set.
How Are The JavaScript-mancy Series Organized? What is There in the Rest of the Books?
The rest of the books are organized in 3 parts focused in the language, the ecosystem and building your first app in JavaScript.
After this introductory book Part I. Mastering the Art of JavaScript-mancy continues by examining object oriented programming in JavaScript, studying prototypical inheritance, how to mimic C# (classic) inheritance in JavaScript. We will also look beyond class OOP into mixins, multiple inheritance and stamps where JavaScript takes you into interesting OOP paradigms that we rarely see in the more conventional C#.
We will then dive into functional programming in JavaScript and take a journey through LINQ, applicative programming, immutability, generators, combinators and function composition.
Organizing your JavaScript applications will be the next topic with the module pattern, commonJS, AMD (Asynchronous module definition) and ES6 modules.
Finally we will take a look at Asynchronous programming in JavaScript with callbacks, promises and reactive programming.
Since adoption of ES6 will take some time to take hold, and you’ll probably see a lot of ES5 code for the years to come, we will start every section of the book showing the most common solutions and patterns of writing JavaScript that we use nowadays with ES5. This will be the perfect starting point to understand and showcase the new ES6 features, the problems they try to solve and how they can greatly improve your JavaScript.
In Part II. Welcome to The Realm Of JavaScript we’ll take a look at the JavaScript ecosystem, following a brief history of the language that will shed some light on why JavaScript is the way it is today, continuing with the node.js revolution and JavaScript as a true cross-platform, cross-domain language.
Part II will continue with how to setup your JavaScript development environment to maximize your productivity and minimize your frustration. We will cover modern JavaScript and front-end workflows, JavaScript unit testing, browser dev tools and even take a look a various text editors and IDEs.
We will wrap Part II with a look at the role of transpiled languages. Languages like TypeScript, CoffeeScript, even ECMAScript 6, and how they have impacted and will affect JavaScript development in the future.
Part III. Building Your First Modern JavaScript App With Angular 2 will wrap up the book with a practical look at building modern JavaScript applications. Angular 2 is a great framework for this purpose because it takes advantage of all modern web standards, ES6 and has a very compact design that makes writing Angular 2 apps feel like writing vanilla JavaScript. That is, you won’t need to spend a lot of time learning convoluted framework concepts, and will focus instead in developing your JavaScript skills to build a real app killing two birds with one stone (Muahahaha!).
In regards to the size and length of each chapter, aside from the introduction, I have kept every chapter small. The idea being that you can learn little by little, acquire a bit of knowledge that you can apply in your daily work, and get a feel of progress and completion from the very start.
Understanding the Code Samples in This Book
How to Run the Code Samples in This Book
For simplicity, I recommend that you start running the code samples in the browser. That’s the most straightforward way since you won’t need to install anything in your computer. You can either type them as you go in the browser JavaScript console (F12
for Chrome if you are running windows or Opt-CMD-J
in a Mac) or with prototyping tools like JsBin, jsFiddle, CodePen or Plunker. Any of these tools is excellent so you can pick your favorite.
If you don’t feel like typing, all the examples are available in jsFiddle/jsBin JavaScriptmancy library: http://bit.ly/javascriptmancy-samples.
For testing ECMAScript 6 examples I recommend JsBin, jsFiddle or the Babel REPL at https://babeljs.io/repl/. Alternatively there’s a very interesting Chrome plugin that you can use to run both ES5 and ES6 examples called ScratchJS.
If you like, you can download all the code samples from GitHub and run them locally in your computer using node.js.
Also keep an eye out for javascriptmancy.com where I’ll add interactive exercises in a not too distant future.
A Note About Conventions Used in the Code Samples
The book has three types of code samples. Whenever you see a extract of code like the one below, where statements are preceded by a >
, I expect you to type the examples in a REPL.
The code after >
is what you need to type and the expression displayed right afterwards is the expected result:
Some expressions that you often write in a REPL like a variable or a function declaration evaluate to undefined
:
Since I find that this just adds unnecessary noise to the examples I’ll omit these undefined
values and I’ll just write the meaningful result. For instance:
When I have a multiline statement, I will omit the >
so you can more easily copy and paste it in a REPL or prototyping tool (jsBin, CodePen, etc). That way you won’t need to remove the unnecessary >
before running the sample:
I expect the examples within a chapter to be run together, so sometimes examples may reference variables from previous examples within the same section. I will attempt to show smallish bits of code at a time for the sake of simplicity.
For more advanced examples the code will look like a program, there will be no >
to be found and I’ll add a filename for reference. You can either type the content of the files in your favorite editor or download the source directly from GitHub.
A Note About the Exercises
In order to encourage you to experiment with the different things that you will learn in each chapter I wrap every single one of them with exercises.
It is important that you understand that there is almost no wrong solution. I invite you to let your imagination free and try to experiment and be playful with your new found knowledge to your heart’s content. I do offer a solution for each exercise but more as a guidance and example that as the one right solution.
In many of the exercises you’ll see the following pattern:
This is completely equivalent to:
I just use a helper function weaves
to make it look like Moolen, the mighty wizard is casting a spell (in this case teleport
).
A Note About ECMAScript 5 and ECMAScript 6,7 within The Book
Everything in programming has a reason for existing. That hairy piece of code that you wrote seven months ago, that feature that went into an application, that syntax or construct within a language, all were or seemed like good ideas at the time. ES6, ES7 and future versions of JavaScript all try to improve upon the version of JavaScript that we have today. And it helps to understand the pain points they are trying to solve, the context in which they appear and in which they are needed. That’s why this book will show you ES5 in conjunction with ES6 and beyond. For it will be much easier to understand new features when you see them as a natural evolution of the needs and pain points of developers today.
How will this translate into the examples within the book? - you may be wondering. Well I’ll start in the beginning of the book writing ES5 style code, and slowly but surely, as I go showing you ES6 features, we will transform our ES5 code into ES6. By the end of the book, you yourself will have experienced the journey and have mastered both ES5 and ES6.
Additionally, it is going to take some time for us to start using ES6 to the fullest, and there’s surely a ton of web applications that will never be updated to using ES6 features so it will be definitely helpful to know ES5.
A Note About the Use of Generalizations in This Book
Some times in the course of the book I will make generalizations for the sake of simplicity and to provide a better and more continuous learning experience. I will make statements such as:
In JavaScript, unlike in C#, you can augment objects with new properties at any point in time
If you are experienced in C# you may frown at this, cringe, raise your fist to the sky and shout: Why!? oh Why would he say such a thing!? Does he not know C#!?. But bear with me. I will write the above not unaware of the fact that C# has the dynamic
keyword and the ExpandoObject
class that offer that very functionality, but because the predominant use of C# involves the use of strong types and compile-time type checking. The affirmation above provides a much simpler and clearer explanation about JavaScript than writing:
In JavaScript, unlike in C# where you use classes and strong types in 99% of the situations and in a similar way to the use of dynamic and ExpandoObject, you can augment objects with new properties at any point in time
So instead of focusing on being correct 100% of the time and diving into every little detail, I will try to favor simplicity and only go into detail when it is conductive to understanding JavaScript which is the focus of this book. Nonetheless, I will provide footnotes for anyone that is interested in exploring these topics further.
Do You Have Any Feedback? Found Any Error?
If you have any feedback or have found some error in this book that you would like to report, then don’t hesitate to drop me an email at jaime@vintharas.com.
A Final Word From the Author
The goal for this series of books is to be holistic. Holistic enough to give a good overview of the JavaScript language and ecosystem, yet contain enough detail to impart real knowledge about how JavaScript really works. That’s a fine line to tread and sometimes I will probably cover too little or too much. If so don’t hesitate to let me know. The beauty of a lean published book is that I have much more room to include improvements suggested by you.
There is a hidden goal as well, that is to make it as fun and enjoyable as possible. Therefore the fantasy theme of the whole book, the conversational style, the jokes and the weird sense of humor. Anyways, I have put my heart and soul into this book and hope you really enjoy it!
Jaime, 2015
Tome I. Mastering the Arcane Art of JavaScript-mancy
Introduction
For many years JavaScript has been frowned upon and looked down on by many developers due to its quirky nature, obscure behaviors and many WTFs that populate its hairy APIs and operations.
Frown upon no more! For with modern design patterns, libraries, tools and the long awaited ECMAScript 6 (ES6, ES2015) writing JavaScript is now a pleasure.
Join me at the school of JavaScript-mancy as we travel along the modern landscape of writing JavaScript in 2015 and beyond, as we discover the organic evolution of this beautiful language and its thriving ecosystem, and delve in the latest features/spells/incantations of the JavaScript Arcana.
You my friend, can no longer ignore JavaScript. JavaScript is the most deployed language on earth, a beautiful and expressive language that supports many paradigms and which has a thriving community that continuously expands and improves its ecosystem with patterns, libraries, frameworks and tools. You don’t want to miss this train.
But JavaScript, though forgiving and specially conceived to be easy to learn, can be either daunting for us that have a strongly-typed mindset and come from languages such as C# or Java or, more often, laughed at as a toy.
For you who consider it daunting and hate working with it worry not! I will show you the most common misconceptions and all the patterns you need to know to become as fluent in JavaScript as you are in C#.
For you who consider it a toy language, something associated not with real programming but with copy-paste coding or scripting to add flare to websites, I will show you all the different patterns and programming paradigms that JavaScript supports and which make it just as good and powerful as C#.
Let’s get started!
Once Upon a Time…
Once upon a time, in a faraway land, there was a beautiful hidden island with captivating white sandy beaches, lush green hills and mighty white peaked mountains. The natives called it Asturi and, if not for an incredible and unexpected event, it would have remained hidden and forgotten for centuries.
Some say it was during his early morning walk, some say that it happened in the shower. Be that as it may, Branden Iech, at the time the local eccentric and today considered the greatest Philosopher of antiquity, stumbled upon something that would change the world forever.
In talking to himself, as both his most beloved companions and his most bitter detractors would attest was a habit of his, he stumbled upon the magic words of JavaScript and the mysterious REPL.
In the years that followed he would teach the magic word and fund the order of JavaScriptmancers bringing a golden age to our civilization. Poor, naive philosopher. For such power wielded by mere humans was meant to be misused, to corrupt their fragile hearts and bring their and our downfall. It’s been ten thousand years, ten thousand years of wars, pain and struggle.
It is said that, in the 12th day of the 12th month of the 12th age a hero will rise and bring balance to the world. That happens to be today.
12th Age, Guardian of Chronicles
This book has a story in it. It is a story of a fantasy1 world where some people can wield JavaScript to affect the world around them, to essentially program the world and bend it to their will. Cool right? The story follows the step of a heroine that comes to this hypothetical world to save it from evil, but of course, she needs to learn JavaScript first. Care to join her in her quest to learn JavaScript and save the world?
The Essential Ingredients Of JavaScript-Mancy
The importance of the fundamentals cannot be enough overstated, the gathering of the proper ingredients for an incantation, the carefulness and caring of the preparations, the timing and intimate knowledge of the rituals, everything affects the end result. To practice is to be, practice as you want to be, for do you want to be an Artful Wizard, or a mediocre one? - Kely Sompsin, Maester of the Guild, Fourth Age
An Introduction to JavaScript-Mancy
I expect the reader of this manuscript to be well acquainted with the basics of programming, but I couldn’t, in good faith, start the book without some sort of introduction to the arts of JavaScript. This first chapter will therefore take you through the whole breadth of the JavaScript language, albeit in a superficial way. I will show you all the basic features of JavaScript, even those of its latest incarnation ECMAScript 6, and how they differ or are similar to C#. I abhorr starting programming books with page after page on for
loops and if
statements so I will attempt to be as brief, interesting and entertaining as I can.
If you feel like you are well versed in the basics of JavaScript (and the new ES6 features) then by all means jump over this chapter, but be aware that there’s a story happening in the examples, so you might be interested in taking a look. In any case, here we go…
JavaScript
JavaScript, as we the guardians of JavaScript-mancy usually call the arts, is a multi-paradigm dynamic programming language. The multi-paradigm bit means that JavaScript lends itself well to different styles (paradigms) of programming like object-oriented or functional programming. The dynamic part means that… well the dynamic part is widely disputed even today… but for all intents and purposes we can say that JavaScript is evaluated as it is executed, there’s no compilation step in which variables are bound, types are checked and expressions analyzed for correctness. The JavaScript runtime defers all this work until the code itself is being executed and this allows for a lot more freedom and interesting applications like metaprogramming 2.
JavaScript is also dynamically typed so a variable can reference many different types during its lifetime and you can augment objects with new methods or properties at any point in time.
I can, for example, summon a minion from the depths of hell using the var
keyword and let it be a number:
And I can do some alchemy thereafter and transform the minion into something else, a string, for example:
I can keep doing that for as long as I want (as long as I have enough mana3 of course), so let’s make my minion
an object:
In JavaScript I don’t need a class to create an object. I can just create an object with whichever properties I desire and then later on augment 4 it with new properties to my heart’s content:
JavaScript Has Some Types
JavaScript supports the following types: Number
, String
, Object
, Boolean
, undefined
, null
and Symbol
.
As you may have guessed, JavaScript has a single type to represent all numbers. Which is pretty nice if you ask me, not having to ever think about doubles, and shorts, and longs and floats…
There’s a string type that works as you would expect any respectable string to behave. It lets you create string literals. Interestingly enough, JavaScript strings support both single ('
) and double quotes ("
):
JavaScript also has a boolean type to represent true
and false
values:
And an object type that we can use to create any new custom types:
JavaScript differs from other languages in that it has two different ways of representing the lack of something. Where C# has null
, JavaScript has both null
and undefined
. Unlike in C#, the default value of anything that hasn’t been yet defined is undefined
, whereas null
must be set explicitly.
This can get even more confusing because of the fact that there’s a third possibility. That a variable hasn’t been declared:
The confusion coming mainly from the error message: abracadabra is not defined. You can just think about these variables as undeclared instead of not defined and stick to the previous definition of undefined
.
ECMAScript 6 brings a new primitive type, the symbol. Symbols can be seen as constant and immutable tokens that can be used as unique IDs.
Later within the book, we’ll see how we can use Symbols to enable new patterns for hiding data in JavaScript.
Everything Within JavaScript Behaves Like an Object
In spite of JavaScript not having the concept of value types or reference types, numbers, strings and booleans behave like C# value types and objects behave like C# reference types. In practice, however, everything within JavaScript can be treated as an object.
Numbers for instance, provide several useful methods:
And so do strings:
Interesting right? If a number is a primitive value type, how come it has methods? Well, what is happening is that, whenever we call a method on a number or other primitive type, the JavaScript runtime is wrapping the primitive value in a special wrapper object. So even though 1
is not an object itself, when JavaScript evaluates (1).toPrecision(3)
it wraps the value within the Number
object on-the-fly. You can test the reverse process and instantiate a number using the wrapper object directly:
Then unwrap the original value with valueOf
:
Even more remarkable than numbers and strings, functions behave like objects. They have their own methods:
And you can even add properties to a function:
Let’s take a quick look at each one of these types and how they work in JavaScript.
Strings in JavaScript
Strings, like in C#, let you represent text literals.
Unlike in C# you can use both single ('
) and double quotes ("
) to create a string. Oftentimes you will see one used to escape the other:
Any string has a number of useful methods:
ES6 also brings a number of new methods like startsWith
, endsWith
, repeat
:
Until recently, there was no such thing as C# String.format
nor StringBuilder
so most injecting values in strings was done using the +
operator or string.concat
:
Fortunately, ES6 brings template strings and a more elegant approach to string interpolation.
Better String Interpolation ES6 Template Strings
The new ES6 Template Strings improve greatly the way you can operate with strings. They allow string interpolation based on the variables that exist in the scope where the template is evaluated, thus providing a much cleaner and readable syntax.
In order to create a template string you surround the string literal with backticks and use ${variable-in-scope}
to specify which variable to include within the resulting string:
Template strings also let you easily create multi-line strings.
Where in the past you were forced to make use of string concatenation and the new line character \n
:
ES6 Template strings let you write a multi-line string in a more straightforward fashion:
Functions in JavaScript
Functions are the most basic building component in JavaScript. As such, they can live more independent lives than methods in C# which are always tied to a class. So, you’ll oftentimes see functions alone in the wild:
JavaScript, in a radically different way than C#, lets you call a function with any number of arguments, even if they are not defined in a function’s signature:
And even with no arguments at all, although depending on the function implementation it may cause some chaos and some mayhem:
You can use the very special arguments
array-like object to get hold of the arguments being passed at runtime to a given function:
Or the finer ES6 rest syntax reminescent of C# params
:
In addition to functions working as… well… functions, they perform many other roles in JavaScript and are oftentimes used as building blocks to achieve higher-order abstractions: they are used as object constructors, to define modules, as a means to achieve data hiding and have many other uses.
ES6 changes this complete reliance on functions a little bit as it provides new higher level constructs that are native to the language, constructs like ES6 classes and ES6 modules which you’ll be able to learn more about later in this series. Indeed throughout this series I’ll show you both ES5 constructs, the present and the past, and ES6 ones, the present-ish and the future, so you’ll feel at home in any JavaScript codebase you happen to work with.
Functions as Values
An interesting and very important aspect of functions in javascript is that they can be treated as values, this is what we mean when we say functions are first-class citizens of the language. It means that they are not some special construct that you can only use in certain places, with some special conditions and grammar. Functions are just like any other type in JavaScript, you can store them in variables, you can pass them as arguments to other functions and you can return them from a function.
For instance, let’s say you want to create a very special logger that prepends your name to any message that you wish to log:
But that was a little bit awkward, what if we return a function with the new functionality that we desire:
If you feel a little bit confused by this don’t worry, we will dive deeper into functional programming, closures and high-order functions later in the series. For now just realize that functions are values and you can use them as such.
JavaScript Has Function Scope
Another very interesting aspect of JavaScript that is diametrically opposed to how things work in C# is the scope of variables. JavaScript variables have function scope and not block scope. This means that functions define new scopes for variables and not blocks of code (if statements, for loops, code between {}
, etc…) which highlights once more the importance of functions in JavaScript.
You can appreciate function scope in all its glory in these examples. First if you declare a single function with an if
block you can verify how the if
block doesn’t define a new scope as you would expect in C#:
But if we replace the if
block with a new function inner
, then we have two scopes:
ES6 let, ES6 const and Block Scope
ES6 attemps to bring an end to the confusion of JavaScript having function scope with the let
keyword that allows you to create variables with block scope. With ES6 you can either use var
for function scoped variables or let
for block scoped ones.
If you rewrite the example we used to illustrate function scope with let
, you’ll obtain a very different result:
Now the x
variable only exists within the if
statement block. Additionally, you can use the const
keyword to declare constant variables with block scope.
ES6 Default Arguments
ES6 finally brings default arguments to JavaScript functions, and they work just like in C#:
ES6 Destructuring
Another nifty ES6 feature is destructuring. Destructuring lets you unwrap any given object into a number of properties and bind them to variables of your choice. You can take advantage of destructuring with any object:
Even when passing an object to a function:
ES6 Arrow Functions
Another great feature brought by ES6 are arrow functions which resemble C# lambda expressions. Instead of writing the obliterate
function as we did before, we can use the arrow function syntax:
And if you have a function with more arguments or statements, you can write it just like we do in C#:
We will dive deeper into arrow functions later in the book and see how they not only provide a terser and more readable syntax but also serve a very important function in what regards to safekeeping the value of this
in JavaScript. (We’ve got ourselves a very naughty this
in JavaScript as you’ll soon appreciate yourself)
OOP and Objects in JavaScript
JavaScript has great support for object-oriented programming with objects literals, constructor functions, prototypical inheritance, ES6 classes and less orthodox OOP paradigms like mixins and stamps.
Objects in JavaScript are just key/value pairs. The simplest way to create an object is using an object literal:
ES6 makes easier to create object literals with syntactic sugar for functions also known as method shorthand:
And for creating properties from existing variables also known as property shorthand:
This works great for one-off objects. When you want to reuse the same type of object more than once you can either use a vanilla factory method or a constructor function with the new
keyword:
Prototypical Inheritance
Yet another big diffence between C# and JavaScript are their inheritance models. JavaScript exhibits what is known as prototypical inheritance. That means that objects inherit from other objects which therefore are called prototypes. These objects create what is known as a prototypical chain that is traversed when the JavaScript runtime tries to determine where in the chain a given method is defined.
Let’s say that you have an object that represents an abstraction for any item that can exist in your inventory:
And a two handed iron sword that in addition to being an item (and an awesome item at that) has its own specific set of traits:
You can take advantage of JavaScript prototypical inheritance to reuse the item properties across many items, by setting the item
object as the prototype5 of the ironTwoHandedSword
(and any other specific items that you create afterwards).
This will establish a prototypical chain, so that, if we attempt to retrieve the sword durability
, the JavaScript runtime will traverse the chain and retrieve the property from the item
prototype:
If, on the other hand, you attempt to access a property that exists in both the prototype and the object itself, the nearest property in the chain will win:
ES6 exposes the __proto__
property that lets you directly assign a prototype through an object literal:
There’s a lot more to prototypical inheritance and the many different OOP paradigms supported by JavaScript. But we’ll look into them further later in the series.
ES6 Classes
A new addition to JavaScript you might have heard about and celebrated are ES6 classes. The existence of ES6 classes doesn’t mean that JavaScript gets classes just like C# and we’re not going to worry about constructor functions and prototypical inheritance anymore. ES6 classes are “just” syntactic sugar over the existing inheritance model and the way we craft objects in JavaScript. That being said, it is a great declarative way to represent constructor/prototype pairs.
A JavaScript class looks very similar to a C# class:
And so does inheritance:
Arrays, Maps and Sets in JavaScript
Up until recently JavaScript had only one single data structure, albeit very verstatile, to handle collections of items: the array. You can create an array using using square brackets []
:
You can mix and match the different elements of an array. There’s no type restrictions so you can have numbers, strings, objects, functions, arrays, etc… in much the same way that you can find the most strange items in a kender’s 6 pouch:
You can access the items of an array via their indexes:
You can also traverse the indexes of an array using the for/in
loop:
And even better the items of an array using ES6 for/of
loop:
Arrays have a lot of cool and useful methods that you can use to add/remove or otherwise operate on the items within the array:
And even LINQ-like methods to perform functional style transformations within an array:
You will learn a ton more about arrays later in the book.
ES6 Spread Operator and Arrays
The ES6 spread operator can also be used to merge or flatten an array within another array:
ES6 Maps and Sets
ES6 gives us magicians two new data structures to work with: maps, a true key/value pair data structure and sets to handle collections of unique items.
You can create a new map using the Map
constructor:
You can even seed a map with existing information by sending an array of key/value pairs7:
In a similar fashion, you create sets using the Set
constructor:
Sets will ensure that you don’t have duplicated data within a collection:
JavaScript Flow Control
JavaScript gives you the classic flow control structures that you are accustomed to: if
, for
, while
loops behave much in the same way in JavaScript than in C# (but for the function scoped variables of course).
In addition to these, JavaScript has the for/in
loop that lets you iterate over the properties of an object:
And the ES6 for/of
loop that lets you iterate over collections8 (arrays, maps and sets):
Logical Operators in JavaScript
Abstract Equality and Strict Equality
JavaScript equality operators behave in a particularly special way. The operators that you are accustomed to use in C# ==
and !=
are called abstract equality operators and evaluate the equality of expressions in a loose way. If the two expressions being evaluated by one of these operators don’t match in type, they’ll be converted to a matching type. For instance, in evaluating the abstract equality of 42
and "42"
, the string will be converted to a number resulting in both values being equal:
Fortunately JavaScript also provides operators that performs strict equality ( ===
and !==
) which is basically a comparison of two values without the implicit type conversion.
Implicit Type Conversion Also Known As Type Coercion
This implicit conversion that takes place in JavaScript gives birth to the concept of truthy and falsey. Since any value can be evaluated as a boolean, we say that some values like an array []
or an object {}
are truthy, and some other values like empty string ''
or undefined are falsey. In the examples below we use the !!
to explicitly convert values to boolean for clarity purposes:
This allows for a terser way to write if
statements
Since troll
is coerced to a boolean type, having the troll
variable holding an object value will evaluate to truthy and having it holding null
or undefined
will be falsey. In either case the if
statement will fulfill its purpose while being much nicer to read.
OR and AND
OR (||
) and AND (&&
) operations also behave in an interesting way. The OR operation will return the first truthy expression or the last falsey expression (if all expressions are falsey):
The AND operator will return the last truthy expression or the first falsey expression (if any falsey expression is encountered):
Exception Handling
Exception handling works similar as in C#, you have your familiar try/catch/finally
blocks:
And you can throw new exceptions with the throw
keyword:
Additionally, you can improve your error semantics and create custom errors by inheriting the Error
prototype.
Regular Expressions
JavaScript also supports regular expressions. You can create a regular expression in two ways, either by wrapping the expression between slash (/
):
Or by creating a RegExp
object:
Strings have built-in support for regular expressions as well with the match
and search
methods:
But Beware, JavaScript Can Be Weird and Dangerous
So far you’ve seen the bests parts of JavaScript and nothing too weird or inconsistent. But sometimes you’ll experience strange behaviors in some less visited corners of JavaScript like any of the following:
Oftentimes you won’t run into these issues when building real web applications and my advice is that you ignore them. Be aware that they exist but just don’t use them, or use patterns or conventions to avoid them.
Concluding
And that was a summary of pretty much the whole JavaScript language. I really hope it has sparkled your interest for JavaScript and that you cannot wait to turn the next page and learn more. But first, let’s make a quick review of what you’ve learned in this chapter.
We’ve seen that JavaScript is a very flexible dynamic language that supports many paradigms of programming and has a lot of great features.
You have learned the many things you can do with strings and ES6 string templates. How functions are very independent entities that can live their own lives completely separate from objects and how they are a fundamental building block of applications in JavaScript. You also discovered arrow functions that resemble lambdas in C# and let you write super terse and beautiful code.
We took a look at objects, object initializers, prototypical inheritance and ES6 classes. We saw the different data structures supported, the versatility of the array and an overview of the new ES6 Map and Set.
We also examined more general language features like the flow control structures and logical operators. We saw the difference between abstract comparison and strict comparison, highlighted the implicit type conversion inherent to JavaScript, the existence of the concepts of truthy and falsey and the way the OR and AND operators work.
Finally we reviewed exception handling and regular expressions, and we saw some of the weird and best-avoided behaviors in JavaScript.
The Basics Of JavaScript Functions
functions, functions everywhere - Buzz Lightyearvascript Explorer
The Basics Of Functions
Functions are the most fundamental building blocks of JavaScript applications. They are the safekeepers of the logic within our programs but also the primitives upon which we build programmatic constructs such as classes and modules.
JavaScript provides different ways to declare and use functions, each with their own nuances and limitations. So given the fact that they are such a fundamental part of the language it is important that you are aware of these characteristics when you are writing JavaScript.
Welcome to the first step in your journey to JavaScript mastery! Let’s get started!
Functions are the Key
Did you know that there are not one but two ways to write functions in JavaScript? Well, now you do. You can either write them as function expressions or function declarations. It will be very helpful for you to understand the difference and the implications of writing functions in either of these two styles because they work in a very different manner that will impact the readability of your code and how easy or hard it is to debug.
This is a function expression:
And this is a function declaration:
As you can appreciate, in their most common incarnations function expressions and function declarations look very similar. That’s why it is especially important to understand that they are actually very different and behave in disparate ways from each other.
Let’s examine each of them in greater detail.
Function Expressions
We use the function expression style whenever we declare a function like an expression, either by assigning it to a variable:
A property within an object:
Or passing it as an argument to another function (like a lambda - note that I am using the term lambda in the sense of function as value):
There are a couple of important considerations you need to take into account when using function expressions like the ones above: they are all anonymous functions - they don’t have a name - and if stored within a variable they are subjected to the same hoisting rules that apply to any other variable in JavaScript. But what is hoisting? And how a function being anonymous can affect our programs?.
JavaScript Arcana: Function Scope and Hoisting
An interesting quirk about JavaScript is that, unlike many other languages, variables in JavaScript have function scope (as opposed to block scope). That is, it is the functions themselves that create scopes for variables and not the blocks. This can be better illustrated by an example:
What happens in this piece of code above is that the JavaScript runtime hoists (moves up) all variables within a function definition to the beginning of the function body. And does it even with variables declared within blocks of code such as if
statements. This means that the function that you see above is equivalent to this one:
Where the scope of the treasure
variable isn’t only the if
statement but the whole function. In yet another example of hoisting the variable i
that we declare inside the for
loop is actually part of the entire function (Shocker!!):
This is the reason why JavaScript developers - seasoned JavaScriptmancers - usually write all variable declarations at the beginning of a function. They do it in order to be more explicit about what is really happening when a function is evaluated and to avoid unnecessary bugs.
If you take a look at jQuery for instance, a popular JavaScript open source library, you’ll be able to appreciate this technique everywhere:
Functions being the stewards of scope of an application is pretty interesting because, all of the sudden, a function is not only used for encapsulating and abstracting a piece of logic but also for structural reasons. That is, a way to organize and distribute bits and pieces of functionality and code. For instance, you’ll often see functions being declared inside other functions:
This probably looks very weird if you are coming from C#. But up until the recent advent of ES6 modules this was the only way we had to group pieces of loosely related functionality.
JavaScript Arcana Resolved: Variables with Block Scope With ES6 let and const
Happily for you and happily for me ES6 comes with not one, but two ways to declare variables with block scope: the new let
and const
keywords. From this point forward I invite you to start using let
and achieve a more C#-like style of writing code where you declare variables closer to where you use them.
And so, if we rewrite the example we used to illustrate function scope with let
, we’ll obtain a very different yet more familiar result:
Now the treasure
variable only exists within the if
statement block.
Alternatively, you can use the const
keyword to declare constant variables with block scope.
Variables declared with the const
keyword behave in a very similar way to C#. Attempting to make the constant refer to a different value will cause an exception.
However, it is important to understand that if the constant refers to an object, you can still modify its properties:
This means that const
only affects the act of binding a value to a variable, and not the act of modifying that value itself. In order to make an object immutable you need to use Object.freeze
but that’s knowledge best kept for another chapter about the beauty of objects. We’ll stick to functions for a little bit longer.
Another aspect of let
and const
that is interesting is that they do not hoist variables to the top of a block. Instead, if you attempt to use a variable before it has been defined you’ll get an exception (cheers for some sane behavior):
Now that you’ve learnt some of the main characteristics of function expressions let’s take a look at the two types of function expressions that are available to you in JavaScript: anonymous function expressions and named function expressions.
Anonymous Function Expressions
Anonymous function expressions are particularly interesting because even though you read the following:
And you may be tempted to think that the name of the function is castFireballSpell
, it is not!?! castFireballSpell
is just a variable we use to store an anonymous function. You can appreciate this anonymity by inspecting the name
property of the function itself:
Luckily for us, as long as an anonymous function is bound to a variable, the developer tools in modern browsers will use that variable when displaying errors in call stacks (which is a savior when debugging):
Even if we use this function as a argument:
However, an unbound anonymous function will show as completely anonymous within the call stack making it harder to debug when errors occur (I will refer to these functions as strict anonymous function from now on):
This lack of name will also affect the ability to use recursion because a function that doesn’t have a name cannot call itself from inside its body. In spite of that and just like in the previous examples, if we have the anonymous function bound to a variable we take a free pass and can take advantage of JavaScript lexical scope to access the function through that variable:
Notice that this is a pretty brittle way of using recursion. In this example we are using the variable castManyFireballsSpell
to access the anonymous function from within itself. If, at some later point in time, you happen to set the variable to another function you’ll get into a pickle. A tricky situation with a very subtle bug where the original function will call this new function instead of itself (so no more recursion and weird unexpected stuff happening).
A strict anonymous function, on the other hand, has no way to refer to itself and thus you lose the ability to use recursion. For instance, this is the case when we define an anonymous function expression and we invoke it right away:
In summary, the fact that common function expressions are anonymous makes them harder to debug and complicates the use of recursion. And the fact that they are hoisted as variables, a trait common to all function expressions, also makes them less readable as we’ll see in a bit with a larger example program.
Let’s see some ways to ameliorate or lessen these issues.
Named Function expressions
You can solve the problem of anonymity that we’ve seen thus far by using named function expressions. You can declare named function expressions by adding a name after the function
keyword:
The example above shows a variable and a function expression both named castFireballSpell
. A named function expression always appears correctly represented in the call stacks even when used as an argument (and not bound to a variable):
This helps while debugging and makes your code more readable since you can read the name of the function and understand what it’s meant to do without looking at its implementation.
An interesting fact about named function expressions is that you cannot call them by their name from the outside:
The name of a function expression is more of an internal identifier that can be used from inside the function body. This is very useful when working with recursion. For instance, if we declare a recursive named function expression and invoke it right away it just works:
In summary, named function expressions improve on anonymous function expressions by increasing readability, improving the debugging process and allowing for a function to call itself.
Function Expressions are Hoisted as Variables
Function expressions are still problematic because they are hoisted like variables. But what does this mean exactly? It means that you can only use a function expression after you have declared it and therefore it forces you to write your code starting from the implementation details and continuing into higher levels of abstraction.
This is the opposite of what you want. Think about it. When you write a class as a C# developer, you start with the public API at the top of the class definition. Then you write the implementation of each method from top to bottom, from higher to lower levels of abstraction so that reading becomes natural. You open a file at the top, understand what it does at a glance by reading the intentional names that compose its public API and then you traverse the file down looking at the implementation details only when you need or want to.
Being forced to start from the opposite direction will have a negative impact in the readability of your code:
If you try to reorder the different functions within the module so that they start from the public API and continue from top to bottom, from higher to lower levels of abstraction you’ll encounter many issues:
In this example we use function expressions to define every function. Because they are hoisted like variables when we try to assign the enchant
function to our magic.enchant
object its value is undefined
. This results in us exposing an undefined
value to the outside world instead of a helpful function to enchant delicious cakes. In a similar way, when we attempt to call the enchant
function before either enchant
or mix
have been initialized we get a TypeError
exception.
In summary, both named and anonymous function expressions are hoisted as variables. This affects their readability and can cause bugs when we try to run a function or expose it as part of the public API of a module before it has been defined. Although you could use let
and const
to prevent hoisting, there’s a better way you can declare your functions: Function declarations.
Function Declarations
Function declarations have some advantages over function expressions:
- They are named, and you can use that name from outside and from within the function.
- They are not hoisted as variables but as a whole, which makes them impervious to hoisting problems.
This is how you write a function declaration:
As you learned just a moment ago, function declarations are hoisted in a very special way. When the JavaScript runtime processes this piece of code:
It’s going to rearrange it by hoisting the whole sayHello
function and only the declaration of the variables message
and sayHi
:
Because of this special hoisting behavior, function declarations will enable you to write your JavaScript modules from higher to lower levels of abstraction just like we discussed earlier and as you can see in this example below:
And, just like function expressions, you can also use function declarations as values (and arguments). Notice the disintegrate
function below:
There’s something interesting happening in this example above that is worthy of note: type coercion. When the body of the disintegrate
function is evaluated, the expression below:
Coerces the thing
variable to a string
type. In the case of the orc
and warg
which are objects that means calling the toString
method and obtaining a string
representation of either of these objects.
Concluding: Prefer Function Declarations and Named Function Expressions
Function expressions have some limitations:
- They are anonymous, which can make them less readable, harder to debug and use in recursion
- They are hoisted as variables which can lead to bugs and forces you to declare them before you can use them
Named function expressions solve the problem of anonymity. They make your vanilla function expressions more readable, easier to debug and enable recursion.
Function declarations solve both problems of anonymity and hoisting (they are hoisted as a whole), and even allow you to write code from higher to lower levels of abstraction.
You can use the let
and const
keywords to solve the problems with hoisting related to function expressions but you don’t get the nice top to bottom narrative that you get with function declarations. That is, with let
and const
you cannot use a function before you have declared it, if you attempt to do so you’ll get an exception.
In summary, and based on the characteristics of functions in JavaScript, prefer named function expressions and function declarations over anonymous function expressions.
Hope you have enjoyed this chapter about the different ways you can write functions in JavaScript. Up next, We will discuss the most common patterns to achieve default values, multiple arguments and function overloading when writing functions in JavaScript and we’ll see how some of the new features in ES6 provide native support for some of these.
Exercises
Useful Function Patterns: Default Arguments
Put yourself in the place of the listener, of the eater, of the reader, of the user of your carefully crafted spells. Think from the outside in, and you'll be rewarded manyfold. Think developer experience!! - Llroc Warrior Poet
Have You Heard Of Defaults?
I don’t know you but I’m always trying to write less code and build beautiful APIs for myself and other developers. One small way to achieve that is by using default arguments. Defaults let you add more intention behind your APIs and provide a shortcut to the most common functionality or task carried out by a function.
In this and the next few chapters we’ll discuss several patterns that you can use to improve the usability of the functions you write in JavaScript: defaults, multiple arguments and function overloading. Let’s get started with defaults in ES5 and ES6.
Using Default Arguments in JavaScript Today
If you have had the chance to take a look at some Javascript code, you may have encountered the following statement and wondered what (the heck) it meant:
Hold on tight because we are about to unveil the mystery. That statement right there has been the prevalent approach to writing defaults in JavaScript for ages. If you do a little of a mental exercise and try to remember what you read about the ||
(OR) operator in the introduction you’ll recall that this operator behaves in quite a special way: It returns the first truthy expression of those being evaluated or the last expression if none is truthy. As usual, this behavior is better illustrated through an example:
Since up until ES6 there was no native support for defaults and using the ||
operator was the most compact way to achieve it, this pattern soon became the de facto standard for defaults throughout the community and is often used in JavaScript applications. You just need to take a sneak peak in any popular open source library to find it used in innumerable situations:
One of the most common use of defaults happens when evaluating the arguments of a function like in this castIceCone
spell:
The castIceCone
function has two arguments: a mana
argument that represents the amount of mana a powerful wizard is going to spend in casting the ice cone and an additional options
object with finer details.
The function makes extensive use of the ||
operator to provide defaults for all possible cases. In the simplest and most convenient of scenarios the user of this function would just call it directly, and when more finesse is needed she or he could populate the richer options
argument:
An alternative way to do defaults is to wrap them within an object.
Defaults with Objects
In addition to relying on the ||
operator, you can use an object to gather your default values. Whenever the function is called you merge the arguments provided by the user with the object that represents the defaults. The default values will only be applied when the actual arguments are missing.
You can define a mergeDefaults
function to perform the merge operation:
And then apply it to the arguments passed to the function like in this castLightningBolt
spell:
Which provides a similar defaults developer experience to that of the first example:
More often though you will probably rely on a popular open source library. Libraries like jQuery, underscore or lodash usually come with a lot of utility functions that you can use for this and many other purposes. For instance, jQuery comes with the $.extend
function and underscore comes with both the _.defaults
and _.extend
functions that could help you in this scenario.
Let’s update the previous example with code from these two libraries:
If you have kept an eye on ES6 you may know that it comes with a native version of the jQuery $.extend
method called Object.assign
. Indeed, you can update the previous example as follows and achieve the same result:
However, if you are planning to use ES6, there’s an even better way to use defaults.
Native Default Arguments with ECMAScript 6
ES6 makes it dead easy to declare default arguments. Just like in C# you use the equal sign "="
and assign a default value beside the argument itself:
JavaScript takes defaults even further because they are not limited to constant expressions like C# optional arguments. In JavaScript, any expression is a valid default argument.
For instance, you can use entire objects as defaults:
If you take a closer look at the end of the example above, you’ll realize that we have a small bug in our function. We are setting a default for the entire options
object but not for parts of it. So if the developer provides an object with the direction
property missing, we will get a strange result (writing undefined
to the console).
We can solve this problem by taking advantage of the new destructuring syntax which allows you to assign argument properties directly to variables within a function, and at the same time provide defaults to parts of an object:
In this example we use argument destructuring {direction='forward'}
to:
-
Extract the property
direction
from the argument provided to the function at once. This allows us to writedirection
instead of the more verboseoptions.direction
that we used in previous examples. -
Provide a default value for the
direction
property in the case that the function is called with a options object that misses that property. It therefore solves the problem with the{duck: 'cuack'}
example.
Finally, taking the freedom of defaults to the extreme, you are not limited to arbitrary objects either, you can even use a function expression as a default (I expect your mind has just been blown by this, this… very… second):
Concluding
Yey! In this chapter you’ve learned several ways in which you can use defaults in JavaScript whether you are using ES5 or ES6 and beyond. Taking advantage of defaults will let you write less code and provide a slightly better user experience to the consumers of the functions that you write.
Up next, more function patterns with multiple arguments and the rest operator!
Exercises
More Useful Function Patterns: Arbitrary Arguments
What works for one, may work for many... - Eccason, Maester of the Aethis
An Arbitrary Number of Arguments
Sometimes you write a function that performs some sort of action based on a single argument. Some time later you realize that it would be nice if you could use that same function, but this time, with an arbitrary number of arguments. You may be tempted to change the interface of the original function to take an array instead of a single item. In doing so, however, you break the code that is using the function and force any future developers to wrap the arguments being sent inside an array, even when there’s only a single argument.
In this specific scenario, you may want to do something different. You may want to keep the function interface as it is and elegantly extend it to support multiple arguments without affecting any existing code. That’s what we do in C# with the params
keyword, and what you can achieve in JavaScript via the arguments
object or ES6 rest parameter syntax.
This is what you’ll learn in this chapter. But first, did you know that JavaScript functions are pretty peculiar about their arguments?
The Craziness Of Function Arguments in JavaScript
JavaScript gives you a lot of freedom when it comes to handling function parameters and arguments. For instance, you can declare a function with a specific number of parameters and, if you wish, call it without any arguments at all.
Imagine a function heal
that casts a healing spell on a person:
This function has an arity of 3, that is, it expects 3 arguments. You can verify this accessing its length
property. (A popular interview question by the way):
Thanks to the magic of JavaScript’s infinite freedom you can call it without any arguments at all. Although this doesn’t mean that it will work:
You can also call it with as many of those 3 arguments as you want:
Or even with more arguments than the parameters defined in the function itself:
It is up to you to implement the body of a function and handle each case as you see fit. But what happens when you want to write a function that takes an arbitrary number of arguments?
Functions with Arbitrary Arguments Right Now!
In C#, whenever we want to write such a function we use the params
keyword. In JavaScript (up to ES5), on the other hand, there’s no keyword nor operator that allows us to do that.
The only possible approach is to use the arguments
object. arguments
, like this
, is a special kind of object present within every function in JavaScript. Its whole purpose is to give access to the arguments used to call a function from inside the function itself.
Think about an obliterate
spell that you could use to completely wipe out an enemy:
But why stop at one? With arguments
you can make an obliterate
spell to wipe out all your enemies at once!
Indeed, we can use our obliterate
function with one or as many arguments as we want. We have extended our function API without breaking it:
As it goes, there are a couple of interesting things to point out in this example.
The first one is the fact that we are sending arguments of different types to the function and they are all treated seamlessly. That’s an example of duck typing in action where an object is defined by what it can do and not by its type. As long as the values that we pass as arguments support the interface the function expects - in this case the toString
method - everything will work just fine.
The second thing to point out is the use of the Array.prototype.slice
function. We use it to convert the arguments
variable into a real array victims
. While you would expect the arguments
variable to be an array, it is not, it is an array-like object (and this, my friend, is another of JavaScript quirks right here).
Array-Like Objects
Here are the things you can do with an array-like object:
Because it is not an array it does not have any of the array functions that you would expect:
Using the slice
function of Array.prototype
allows you to convert arguments
to an array and take advantage of all the nice array functions. This is what we did with the obliterate
function:
Alternatively, you can use the ES6 Array.from
method for a more natural conversion of an array-like object into an array:
In the specific case of the arguments
object ES6 rest syntax offers a much better alternative9 as you’ll find out soon.
Native Arbitrary Arguments with ES6 Rest Parameters
ES6 comes with a native way to handle arbitrary arguments: rest parameters.
All the complexity of using the arguments
object in the previous examples can be substitued by rest parameters and handled seamlessly:
When using rest parameters, victims
becomes an array automatically so there’s no need to perform additional conversions. Indeed, if we use the new obliterate
function as we did before it works perfectly:
Rest paratemers can also be used in combination with normal parameters. For instance, imagine that the obliterate
spell had an extra effect on the first enemy it encountered. We could rewrite it like this:
Upon using this malignant spell the first enemy would be removed from existence completely and utterly:
Note how easily the rest parameters capture all the remaining arguments after unfortunateVictim
. Beautiful!
You now know different ways to implement a function that takes an arbitrary number of arguments. A function that provides the same API regardless of being called with one or many arguments. But what if you just happen to have an array? What happens if the output of another function is an array of enemies that need to be obliterated? Well, that’s when the ES6 spread operator comes in handy.
The ES6 spread operator, among other things that you’ll learn later in this book, lets you seamlessly call these type of functions using an array as argument:
Note how the spread operator ...mortalEnemies
is super similar to rest parameters syntax but performs the opposite operation, instead of gathering arguments into an array, it spreads an array into arguments.
Concluding
Congratulations! You have cleared another obstacle in the path to writing functions with beautiful and thoughtful APIs.
Function parameters and arguments are yet another example of the flexibility and freedom that JavaScript offers. In JavaScript you can call a function with as many argument as you want regardless of the signature of the function itself.
In some ocassions you’ll need to design a function that takes an arbitrary number of arguments. If you are using ES5, you can take advantage of the arguments
object. The arguments
object is present in every function and gives you access to the arguments with which a function was called. Unfortunately, it is an array-like object and you may need to convert it to an array before you can use it. If you are using ES6 or above, rest parameters offer a great developer experience similar to C# params
. You can combine rest parameters with normal parameters and even call one of these special functions with an array using the spread operator.
In the next chapter you’ll find out how to override functions (and methods) in JavaScript.
Exercises
More Useful Function Patterns: Function Overloading
One same API, to provide similar function, that's a smart thing, memorable, familiar, consistent - Siwelluap Chieftain of the twisted fangs
Have you Heard About The Marvels Of Overloading?
In the last couple of chapters we learned some useful patterns with functions in JavaScript that helped us achieve defaults and handling arbitrary arguments. We also saw a common thread: The fact that ES6 comes with a lot of new features that make up for past limitations of the language. Features like native defaults and rest parameters that let you solve these old problems in a more concise style.
This chapter will close this section - useful function patterns - with some tips on how you can achieve function overloading in JavaScript.
Function overloading helps you reuse a piece of functionality and provide a unified API in those situations when you have slightly different arguments yet you want to achieve the same thing. Unfortunately, there’s a problem with function overloading in JavaScript.
The Problem with Function Overloading in JavaScript
There’s a slight issue when you attempt to do function overloading in JavaScript like you would in C#. You can’t do it.
Indeed, one does not simply overload functions in JavaScript willy nilly. Imagine a spell to raise a skeleton army:
And now imagine that you want to overload it to accept an argument mana
that will affect how many skeletons can be raised from the dead at once:
If you now try to execute the raiseSkeleton
function with no arguments you would probably expect the first version of the function to be called (just like it would happen in C#). However, what you’ll discover, to your dismay, is that raiseSkeleton
has been completely overwritten:
In JavaScript, you cannot override a function by defining a new one with the same name and a different signature. If you try to do so, you’ll just succeed in overwriting your original function with a new implementation.
How Do We Do Function Overloading Then?
Well, as with many things in JavaScript, you’ll need to take advantage of the flexibility and freedom the language gives you to emulate function overloading yourself. In the upcoming sections you’ll learn four different ways in which you can achieve it, each with their own strengths and caveats:
- Inspecting arguments
- Using an options object
- Relying on ES6 defaults
- Taking advantage of polymorphic functions
Function Overloading by Inspecting Arguments
One common pattern for achieving function overloading is to use the arguments
object to inspect the arguments that are passed into a function:
Following this pattern you inspect each argument being passed to the overloaded function(or even the number of arguments) and determine which internal implementation to execute:
This approach can become unwieldy very quickly. As the overloaded functions and their parameters increase in number, the function becomes harder and harder to read, maintain and extend.
At this point you may be thinking: ”…checking the type of the arguments being passed? seriously?!” and I agree with you, that’s why I like to use this next approach instead.
Using an Options Object
A better way to achieve function overloading is to use an options object. This object acts as a container for the different parameters a function can consume:
This allows you to call a function with different arguments:
It is not strictly function overloading but it provides the same benefits: It gives you different possibilities in the form of a unified API, and additionally, named arguments and easy extensibility. That is, you can add new options without breaking any existing clients of the function.
Here is an example of both argument inspecting and the options object patterns in the wild, the jQuery ajax function:
Relying on ES6 Defaults
Although ES6 doesn’t come with classic function overloading, it brings us default arguments which give you better support for function overloading than what we’ve had so far.
If you reflect about it, default arguments are a specialized version of function overloading. A subset of it, if you will, for those cases in which you can use an increasing number of predefined arguments:
Taking Advantage of Polymorphic Functions
Yet another interesting pattern for achieving function overloading is to rely on JavaScript great support for functional programming. In the world of functional programming there is the concept of polymorphic functions, that is, functions which exhibit different behaviors based on their arguments.
Let’s illustrate them with an example. Our starting point will be this function that we saw in the inspecting arguments section:
We will take it and decompose it into smaller functions:
And now we create an abstraction (functional programming likes abstraction) for a function that executes several other functions in sequence until one returns a valid result. Where a valid result will be any value different from undefined
:
dispatch
lets us create a new function that is a combination of all the previous ones: raiseSkeletons
, raiseSkeletonCreature
and raiseSingleSkeleton
:
This new function will behave in different ways based on the arguments it takes. It will delegate any call to each specific raise skeleton function until a suitable result is obtained.
Note how the last raiseSingleSkeleton
is a catch-all function. It will always return a valid result regardless of the arguments being sent to the function. This will ensure that however you call raiseSkeletonFunctionally
you’ll always have a default implementation or valid result.
A super duper mega cool thing that you may or may not have noticed is the awesome degree of composability of this approach. If we want to extend this function later on, we can do it without modifying the original function. Take a look at this:
We now have a raiseAdvanced
function that augments raiseSkeletonFunctionally
with the new desired functionality represented by raiseOnSteroids
:
This is the OCP (Open-Closed Principle)10 in all its glory like you’ve never seen it before. Functional programming is pretty awesome right? We will take a deeper dive into functional programming within the sacred tome of FP later in the series and you’ll get the chance to experiment a lot more with both higher-order functions and function composition alike.
Concluding
Although JavaScript doesn’t support function overloading you can achieve the same behavior by using different patterns: inspecting arguments, using an options object, relying on ES6 defaults or taking advantage of polymorphic functions.
You can use the arguments
object and inspect the arguments that are being passed to a function at runtime. You should only use this solution with the simplest of implementations as it becomes unwieldly and hard to maintain as parameters and overloads are added to a function.
Or you can use an options object as a wrapper for parameters. This is both more readable and maintanaible than inspecting arguments, and provides two additional benefits: named arguments and a lot of flexibility to extend the function with new parameters.
ES6 brings improved support for function overloading in some situations with native default arguments.
Finally, you can take advantage of functional programming, compose your functions from smaller ones and use a dispatching mechanism to select which function is used based on the arguments.
Exercises
On the Art of Summoning Servants and Critters, Or Understanding The Basics of JavaScript Objects
Things are ideas, ideas are abstractions, abstractions are objects, objects are things. That's the secret of JavaScript-mancy - Branden Iech, Meditations
An Army of Objects
Hello JavaScriptmancer! It is time to get an introduction to the basics of objects in JavaScript. In this chapter you’ll learn the beauty of the object initializer and the nice improvements ES6 brings to objects. If you think that you already know this stuff, think twice! There is more than one surprise in this chapter and I promise that you’ll learn something new by the end of it.
Let’s get started! We’ll start by concentrating our efforts in the humble object initializer. This will provide a foundation that we can use later when we come to the tome of object-oriented programming in JavaScript and prototypical inheritance.
Objects it is!
Object Initializers (a.k.a. Object Literals)
The simplest way to create an object in JavaScript is to use an object initializer:
You can add properties and methods inside your object initializer to your heart’s content:
And, of course, if you call a method within the critter
object it behaves as you have come to expect from any good self-respecting method:
As you saw in the introduction of the book, you can augment any11 object at any time with new properties:
And use these new abilities to great devastation:
Alternatively, you can access any property and method within an object by using the indexing notation via []
:
Although a little bit more verbose, this notation lets you use special characters as names of properties and methods:
As you can see in many of the examples above, you can use the this
keyword to reference the object itself and thus access other properties within the same object.
Getters and Setters
Getters and setters are an often overlooked feature within object initializers. You’ll even find fairly seasoned JavaScript developers that don’t know about their existence. They work exactly like C# properties and look like this:
Notice the strange get damage()
function-like thingy? That’s a getter. In this case, it represents the read-only property damage
that is calculated from other two properties strength
and dexterity
.
Getters are extremely useful when you need to define computed properties, that is, properties described in terms of other existing properties. They save you from needing to keep additional and unnecessary state that brings the additional burden of keeping it in sync with the properties it depends on (in this case strength
and dexterity
).
We can also use a backing field to perform additional steps or validation:
In this example we ensure that the _hp
property of the giant bat cannot go below 0
(because you can’t be deader than dead, unless you are a necromancer that is):
Method Overloading
Method overloading within object initializers works just like with functions. As we saw in the previous chapter, if you try to overload a method following the same pattern that you are accustomed to in C#:
You’ll just succeed in overwriting the former jump
method with the latter:
Instead, use any of the patterns that you saw in the previous chapter to achieve method overloading. For instance, you can inspect the arguments being passed to the jump
function:
This provides a naive yet functioning implementation of method overloading:
Creating Objects With Factories
Creating one-off objects through object initializers can be tedious, particularly whenever you need more than one object of the same “type”. That’s why we often use factories13 to encapsulate object creation:
Once defined, we can just use it to instantiate new objects as we wish:
There’s a lot of cool things that you can do with factories in JavaScript. Some of them you’ll discover when you get to tome of OOP where we will see an alternative to classical inheritance in the shape of object composition via mixins. In the meantime let’s take a look at how to achieve data privacy.
Data Privacy in JavaScript
You may have noticed by now that there’s no access modifiers in JavaScript, no private
, public
nor protected
keywords. That’s because every property is public, that is, there is no way to declare a private property by using a mere object initializer. You need to rely on additional patterns with closures to achieve data privacy, and that’s where factories come in handy.
Imagine that we have the previous example of our monster
but now we don’t want to reveal how we have implemented positioning. We would prefer to hide that fact from prying eyes and object consumers. If we decide to change it in the future, for a three dimensional representation, polar coordinates or who knows what, it won’t break any clients of the object. This is part of what I call intentional programming, every decision that you make, the interface that you build, the parts that you choose to remain hidden or public, represent your intentions on how a particular object or API should be used. Be mindful and intentional when you write code. Back to the monster
:
Let’s take a closer look to that example. We have extracted the position
property outside of the object initializer and inside a variable within the stealthyMonster
scope (remember that functions create scopes in JavaScript). At the same time, we have updated the movesTo
function, which creates its own scope, to refer to the position
variable within the outer scope effectively creating a closure.
Because position
is not part of the object being returned, it is not accessible to clients of the object through the dot notation. Because the movesTo
becomes a closure it can access the position
variable within the outside scope. In summary, we got ourselves some data privacy:
ES6 Improves Object Initializers
ES6 brings some improvements to object initializers that reduce the amount of code needed to create a new object. For instance, with ES6 you can declare methods within objects using shorthand syntax:
As you can appreciate from the movesTo
and toString
methods in this example above, using shorthand notation lets you skip the function
keyword and collapse the parameters of a function directly after its name.
Additionally you can apply shorthand syntax to object properties. When you write factory functions you’ll often follow a pattern where you initialize object properties based on the arguments passed to the factory function:
Where you have a little bit of redundant code in type: type
and hp: hp
. Property shorthand syntax removes the need to repeat yourself by letting you write the property/value pair only once. So that the previous example turns into a much terser factory method:
And here you have a complete example where we use both method and property shorthand to get the ultimate sugary monster:
Finally, with the advent of ES6 you can use any expression as the name of an object property. That is, you are no longer limited to normal names or using the square brackets notation that handles special characters. From ES6 onwards you’ll be able to use any expression and the JavaScript engine will evaluate it as a string (with the exception of ES6 symbols which we’ll see in the next section). Take a look at this:
This example let’s you appreciate how any expression is valid. We’ve used the result of evaluating a function (() => 'loves!')()
, a property from another object sugaryOoze.type
and even an arrow function theArrow
as property names. If you inspect the object itself, you can see how each property has been intrepreted as a string:
And you can retrieve them with the []
(indexing) syntax:
Use cases for this particular feature? I can only think of some pretty far-fetched edge cases for dynamic creation of objects on-the-fly. That and using symbols as property names wich gracefully brings us to ES6 symbols and how to take advantage of them to simulate data privacy.
ES6 Symbols and Data Privacy
Symbols are a new type in JavaScript. They were conceived to represent constants and to be used as identifiers for object properties. The specification even describes them as the set of all non-string values that may be used as the key of an object property 14. They are immutable and can have a description associated to them.
You can create a symbol using the Symbol
function:
And you can add a description to the symbol by passing it as an argument to the same function. This will be helpful for debugging since the toString
method will display that description:
Each symbol is unique and immutable, so even if we create two symbols with the same description, they’ll remain two completely different symbols:
ES6 symbols offer us a new approach to data privacy in addition to closures. Properties that use a symbol as name (or key) can only be accessed by a reference to that symbol (the very same symbol used to identify the property). Because of this special characteristic, if you don’t expose a symbol to the outer world you have provided yourself with data privacy. Let’s see how this works in practice:
Since outside of the flyingMoster
function we don’t have a reference to the symbol position
(it is scoped inside the function), we cannot access the position property:
And because each symbol is unique we cannot access the property using another symbol with the same description:
If everything ended here the world would be perfect, we could use symbols for data privacy and live happily ever after. However, there’s a drawback: The JavaScript Object
prototype provides the getOwnPropertySymbols
method that allows you to get the symbols used as properties within any given object. This means that after all this trouble we can access the position property by following this simple procedure:
So you can think of symbols as a soft way to implement data privacy, where you give a clearer intent to your code, but where your data is not truly private. This limitation is why I still prefer using closures over Symbols.
Concluding
In this chapter you learned the most straightforward way to work with objects in JavaScript, the object initializer. You learned how to create objects with properties and methods, how to augment existing objects with new properties and how to use getters and setters. We also reviewed how to overload object methods and ease the repetitive creation of objects with factories. We wrapped factories with a pattern for achieving data privacy in JavaScript through the use of closures.
You also learnt about the small improvements that ES6 brings to object initializers with the shorthand notation for both methods and properties. We wrapped the chapter with a review of the new ES6 Symbol type and its usage for attaining a soft version of data privacy.
Exercises
Mysteries of the JavaScript Arcana: JavaScript Quirks Demystified
Beware of any assumptions, distrust any preconceptions, forgo your experience, and think with the mind of a beginner. - Appa Ojnh The White Sage
A Couple of Tips About JavaScript Quirks and Gotchas
While JavaScript looks a lot like a C-like language, it does not behave like one in many ways. This, I would say, is the biggest reason why C# developers get so confused when they come to JavaScript.
If you’ve followed the book closely, you may have noticed that I have decided to call these unexpected behaviors the JavaScript Arcana. You have already seen several examples of these shadowy features thus far. Let’s make a quick summary of them:
- Function scope and variable hoisting
- Array-like objects
- Function overloading
We’ll start this chapter by making a short review of the quirks that you’ve already learned (repetition is a great tool for learning). And we’ll continue by diving deeper into these other parts of the JavaScript Arcana:
- The sneaky
this
keyword - Global scope as a default
- Type coercion madness
- JavaScript strict mode
We will focus particularly in the obscure behavior of the this
keyword, our most dangerous foe. I expect that what you will learn in this chapter will save you from unmeasurable frustration in the future.
A Quick Refresher of the JavaScript Arcana 101
In The Basics of JavaScript Functions we saw how JavaScript has function scope. That is, as opposed to C# where every block of code creates a new scope, in JavaScript it is only functions that create new scopes. Every time you declare a variable through the var
keyword it is scoped to its containing function. You also learned the concept of hoisting and how the JavaScript runtime moves your variable declarations to the top of a function body. Finally, you discovered how ES6 brings the let
and const
keywords that give you the ability to declare block-scoped variables and forget about the headaches of hoisting and function-scoped variables.
In Function Patterns: Arbitrary Arguments you learned about the arguments
object. It can be accessed within every function to retrieve the arguments being passed to that function at runtime. You saw how the arguments
object, although it looks like an array, it is actually what we call an array-like object. Array-like objects can be enumerated, indexed and have a length
property but they lack all array methods. You also discovered how to convert these objects to actual arrays using Array.prototype.slice
(or Array.from
) and how the new ES6 rest operator solves the arguments
issue completely.
In Function Patterns: Overloading you learned how you cannot overload JavaScript functions or methods in the same way that you do in C#. Instead, you can use several patterns to achieve the same effect: Argument inspection, options objects, ES6 default arguments or functional programming with polymorphic functions.
Now that we’ve warmed up to JavaScript weirdest features let’s take a look at the behavior of this
.
This, Your Most Dangerous Foe
One of the most common problems when a C# developer comes to JavaScript is that it expects this
to work exactly as it does in C#. And She or He or Zie will write this common piece of code unaware of the terrible dangers that lurk just one HTTP call away…
In this code example we are trying to retrieve a collection of users from the GitHub API. We perform an AJAX15 request using jQuery getJSON
and if the request is successful the response is passed as an argument to the updateUsers
function.
The example throws an exception cannot read property 'push' of undefined
which is the JavaScript version of our well known nemesis: The NullReferenceException
(we meet again). Essentially, when we evaluate the updateUsers
function, the this.users
expression takes the value of undefined
. When we try to execute this.users.push(users)
we’re basically calling the method push
on nothing and thus the exception being thrown.
In order to understand why this is happening we need to learn how this
works in JavaScript. In the next sections we will do just that. By the end of the chapter, when we have demystified this
and become this-xperts, you’ll be able to understand what is the cause of the error.
JavaScript Meets This
So this
in JavaScript is weird. Unlike in other languages, the value of this
in JavaScript depends on the context in which a function is invoked. Repeat. The behavior of this
in JavaScript is not 100% stable nor reliable at all times, it depends on the context in which a function is invoked.
This essentially means that depending on how you call a function, the value of this
inside that function will vary. We can distinguish between these four scenarios:
-
this
and objects -
this
unbound -
this
explicitly -
this
bound
This And Objects
In the most common scenario for an OOP developer we call functions as methods. That is, we call a function that is a property within an object using the dot notation.
If we have a hellHound
spawned in the pits of hell with the ferocious ability of breathing fire:
When we call its attackWithFireBreath
method using the dot notation this
will take the value of the object itself:
Nothing strange here. This is the version of this
we know and love from C#. Things get a little bit trickier in the next scenario.
This Unbound
In JavaScript you can do crazy things. Things like invoking a method without the context of the object in which it was originally defined. Since functions are values we can just save the attackWithFireBreath
method within a variable:
And invoke the function via the newly created variable:
Ooops! What did just happen here? this
is no longer the hell hound but the Window
object. You may be asking yourself: What? And here comes the weird part that you need to remember: Whenever you invoke a function without an object as context the this
automatically becomes the Window object
.
The Window16 object in JavaScript represents the browser window and contains the document object model (also known as DOM) an object representation of the elements within a website.
As a cool exercise, you can now take that free function and add it to another object zandalf
different from the original:
Then call it as a method with the dot notation:
And again, when we invoke the original function in the context of an object, even when it is another one different from the original, this
takes the value of that object.
Let’s make a summary of what you’ve seen up until now:
- Call a function in the context of an object and
this
will take the value of the object - Call a function without context and
this
will take the value of theWindow
object. Unless you are in strict mode in which case it will take the value ofundefined
.
This Explicitly
All functions in JavaScript descend from the Function
prototype. This prototype provides two helpful methods that allow you to explicitly set the context in which to execute a function: call
and apply
.
Take the attackWithFireBreath
function from the last example. This time, instead of calling it directly, we use its call
method and pass the object zandalf
as an argument:
The object zandalf
becomes the context of the function and thus the value of this
. Likewise, if we call the apply
method on the same function and pass an object hellHound
as argument:
We can verify how the object hellHound
becomes the context of the function and the value of this
.
But, what happens if the original function has paremeters? Worry not! Both call
and apply
take additional arguments that are passed along to the original function. Take this function attackManyWithFireBreath
that unleashes a terrible breath of fire on many unfortunate targets:
The call
method let’s you specify a list of arguments separated by commas in addition to the value of this
:
Likewise, apply
takes an array of arguments:
And that’s how you can set the value of this
explicitly. Let’s recapitulate what we’ve learned so far:
- Call a function in the context of an object and
this
will take the value of the object - Call a function without context and
this
will take the value of theWindow
object. Unless you are in strict mode in which case it will take the value ofundefined
. - Call a function using
call
andapply
passing the context explicitly as an argument andthis
will take the value of whatever you pass in.
This Bound
As of ES5, the Function
prototype also provides a very interesting method called bind
. bind
lets you create new functions that always have a fixed context, that is, a fixed value for this
17.
Let’s use bind
to set a fixed value for this
in our original attackWithFireBreath
function. bind
will return a new function attackBound
that will have this
with a value of our choosing. In this case, it will be hellHound
:
After using bind
, the value of this
is bound to the hellHound
object even if you are not using the dot notation:
Moreover, if you assign the attackBound
method to another object and call it using the dot notation, the attackBound
method is executed in the context of the original object hellHound
. That is, after binding a function to a context with bind
, the context will remain the same even after assigning the function to another object:
Once a function is bound it is not possible to un-bound it nor re-bind it to another object:
But you can always use the original unbound function to create new bound versions through subsequent calls to bind
with different contexts:
Concluding This
In summary, this
can take different values based on how a function is invoked. It can:
- Be an object if we call a function within an object with the dot notation
- Be the
Window
object orundefined
(strict mode) if a function is invoked by itself - Be whichever object we pass as argument to
call
orapply
- Be whichever object we pass as argument to
bind
.
If now that you are a this-xpert we go back to the original example you will be able to spot the problem at once. Since the updateUsers
function is a callback, it is not invoked in the context of the UsersCatalog
object. Callbacks are invoked as normal functions, and thus in the context of the Window
object (or undefined
in in strict mode). Because of this, the value of this
within updateUsers
wouldn’t be catalog
but undefined
18.
Because this
is not the catalog
object, it doesn’t have a users
property and thus the resulting cannot read property of undefined
error:
You can solve this issue in either of two ways. You can take advantage of JavaScript support for closures, declare a self
variable that “captures” the value of this
when it refers to the UsersCatalog
object and use it within the closure function as depicted below (a very common pattern in JavaScript):
Or you can take advantage of bind
and ensure that the function that you use as callback is bound to the object that you want:
Later within the book, you’ll see how ES6 arrow functions can also lend you a hand in this type of scenario.
Global Scope by Default and Namespacing in JavaScript
As you will come to appreciate by the end of the book, JavaScript has a minimalistic design. It has a limited number of primitive constructs that can be used and composed to achieve higher level abstractions and other constructs that are native to other languages. One of these constructs are namespaces.
Since we do not have the concept of namespaces, variables that are declared in a JavaScript file are part of the global scope where they are visible and accessible to every JavaScript file within your application. Yey! Party!
The problems with global variables are well known: they tightly couple different components of your application and they can cause name collisions. Imagine that you have several JavaScript files declaring variables with the same names but performing different tasks. Or imagine importing third party libraries that could overwrite your own variables. Chaos and destruction!! Because of these problems we want to completely avoid the use of global variables, yet we lack support for namespaces in JavaScript… What to do?
We can use objects to emulate the construct of namespaces. A commonly used pattern is depicted below where we use what we call an IIFE (immediately invoked function expression) to create/augment a namespace:
An immediately-invoked function expression is just that, a function expression that you invoke immediately. By virtue of being a function it creates a new scope where you can safely have your variables and avoid name collisions with the outside world. If you were to declare a variable with the same name of an existing variable in an outer scope, the new variable would just shadow the outer variable.
By immediately invoking the function you can extend the window.armory
object with whichever properties you desire, creating a sort of public API for the armory
object that becomes a namespace or module. A container where you can place properties and functions and expose them as services for the rest of your application.
We will come back to namespacing and higher level code organization in JavaScript within the tome on JavaScript modules.
Type Coercion Madness
In the basic ingredients of javascript-mancy you learned a little bit about type coercion in JavaScript. You learn how JavaScript provides the ==
and !=
abstract equality operators that let you perform loose equality between values and the ===
and !==
operators that perform strict equality.
By using the first set of operators JavaScript will try to coerce the types being compared to a matching type before performing the comparison, whilst the second set of operators expect a matching type. You also learned how type coercion creates the concept of falsey and truthy by assigning true
and false
to different values and types when being converted to boolean.
I thought it would be interesting for you to learn a little bit more about this JavaScript feature and about its possible pitfalls.
JavaScript was designed to be an accessible language19, a language that even a layman, someone with no prior programming experience could use to create interactive websites. A welcoming language that would help anyone to write their own web applications and solve their own problems. You can see this vision clearly in many of the features of JavaScript, even in some of the most controversial ones. If you think about it from this perspective, it doesn’t feel so weird that the following statement evaluates to true:
For is not 42
equal to '42'
? Don’t both refer to the same number? Does it really matter that they have different types? And so we have implicit conversion of types.
In my experience, taking advantage of type coercion usually results in more terse code:
Taking advantage of the strict equality usually results in more correct, less bug-prone code:
In the first case the condition will be satisfied as long as troll
has a truthy value: It could be an object, an array, a string, a number different than 0
. In the second case, the condition will be satisfied whenever troll
is not null nor undefined (so even it troll
is equal to 0
as opposed to the previous example). Expressiveness or correctness, choose the one that you prefer.
The truthy and falsey values for the most common types are as follow (note how we use the !!
to explicitly convert every value to booleans). Both arrays and objects are truthy, even when they are empty:
A non-empty string is truthy while an empty string is falsey:
Numbers are truthy but for 0
that is falsey:
undefined
and null
are always falsey:
Using JavaScript in Strict Mode
From ES5 onwards you can use strict mode to get a better experience with JavaScript. One of the main goals of strict mode is to prevent you from falling into common JavaScript pitfalls by making the JavaScript runtime more proactive in throwing errors instead of causing silent ones or unwanted effects.
Take the example of the value of this
in callbacks. Instead of setting the value of this
to the Window
object, when you use strict mode the value of this
becomes undefined
. This little improvement prevents you from accessing the Window
object or extending it by mistake, and will alert you with an error as soon as you try to do it. Short feedback loops and failing fast are sure recipes for success.
Other improvements that come with strict mode are:
- trying to create a variable without declaring it (with
var
,let
orconst
) will throw an error. Without strict mode it will add a property to theWindow
object. - trying to assign a variable to NaN, or to a read-only or non-writable property within an object throws an exception
- trying to delete non-deletable properties within an object throws an exception
- trying to have duplicated names as arguments throws a syntax error
- and more explicit errors that will help you spot bugs faster
Additionally with strict mode enabled the JavaScript runtime is free to make certain assumptions and perform optimizations that will make your code run faster. If you want to learn more about the nitty-gritty of strict mode I recommend that you take a look at the MDN (Mozilla Developer Network), the best JavaScript resource in the web.
Enabling Strict Mode
You can enable strict mode by writing 'strict mode';
at the top of a JavaScript file. This will enable strict mode for the whole file:
Alternatively, you can use the strict mode declaration at the top of a function. This will result in the strict mode only being applied within that function:
Wrapping your strict mode declarations inside a function will prevent the strict mode from being applied to code that may not be prepared to handle strict mode. This can happen when concatenating strict mode scripts with non-strict mode scripts like external third party libraries outside of your control.
ES6 modules always use strict mode semantics.
Concluding
In this chapter you learned about the weirdest bits of JavaScript, the mysterious JavaScript Arcana. You started the chapter by reviewing parts of the JavaScript Arcana that you read about in previous chapters: function scope and variable hoisting, array-like objects and function overloading.
You continued taking a look at the sneaky this
keyword, and understood how its value depends on the context in which a function is executed:
- If you invoke a function as a method using the dot notation, the
this
value will be the object that holds that method. - If you call a function directly the value of
this
will be theWindow
object (orundefined
in strict mode). - If you call a function using either
call
,apply
orbind
, the value ofthis
will be set to the object that you pass as argument to either of these functions. - You can use
bind
to create a new version of a function that is bound to a specific object. That is, in that new funtionthis
becomes the object for all eternity.
You saw how JavaScript assumes global scope by default and how you can achieve a similar solution to namespaces by using objects to represent them and organize your code. You examined the concept of IIFE (Immediately Invoked Function Expression) and how you can use it to create an isolated scope to declare your variables and add them to a namespace object.
After that you reviewed type coercion in JavaScript to finally wrap the chapter examining strict mode, a more restricted version of JavaScript that attempts to help you find bugs faster by failing more loudly.
Exercises
A Guide to Strings, Finding the Right Words and Proper Spell Intonation
Klaatu... verata... n... Necktie. Nectar. Nickel. Noodle. - Ash Epic Hero of Ages
Find the Right Words You Must
The use of words, text and text manipulation is commonplace in applications today. Often times applications will provide some sort of user interface as a way to allow user interaction. This UI will contain a myriad of textual information in various forms like labels, tooltips, help texts, text-based content, etc. Even applications that don’t expose a user interface will often log information to the filesystem or to analytics services for troubleshooting and monitoring.
JavaScript, like many other languages, has a primitive type that catters to all your text representation and manipulation needs, the string. In this chapter you’ll learn all you need to know about strings in JavaScript and the exciting new features that come with ES6: template literals and tags.
Let’s start with the basics first!
The Basic Of Strings
You create a string by either using single '
or double quotes "
.
You will often use a single quoted '
string to include "
double quotes inside the string and vice versa:
You can concatenate two strings using the +
operator:
The +
operator is often used to inject values within a string and thus create text based on data:
You can also create multiline strings using the same operator:
Or, alternatively, with a backslash at the end of each line \
:
Additionally, you can insert new lines using the newline character ‘\n’:
As you may have deduced from the previous example, JavaScript uses the backslash `\’ as escape character:
Now that you’ve got a better grasp of strings in JavaScript, let’s take a look at the different operations you can perform on them.
Are Strings Arrays of Characters?
JavaScript strings are not arrays of characters, they behave more like array-like objects. They have a length
property, they can be enumerated and indexed but they lack most of the methods of an array. They are also immutable.
Even though strings are not arrays, you can use some of the array functions on a string by borrowing them from Array.prototype
. For instance, you can traverse each character in a string using forEach
:
Or inject an arbitrary string between each character with join
:
However, if we try to use reverse
it throws an error:
The error message gives us some hints as to why reverse
doesn’t work: The implementation of reverse is trying to do an in-place string reversal. Because strings are immutable, attempting to replace the first character in a string with the last one causes an error and therefore the "cannot assign to read only property '0'"
.
Remember, you can use any array methods on strings as long as they don’t attempt to mutate the original string.
Performing Operations with strings
In addition to these array methods, the string type also provides its own series of methods to help you perform the most common text operations.
You can concatenate strings with concat
just like you did with the +
operator:
You can obtain an uppercase or lowercase version of an existing string using toUpperCase
and toLowerCase
:
You can extract a character at a specific position with chartAt
:
The indexOf
method returns the position of the first occurrence of a piece of text within a string.
You’ll often see it used to find out whether a piece of text exists in a string by comparing it to -1
:
Alternatively you can use the search
method. It is an enhanced version of indexOf
that allows you to specify what you are looking for using a regular expression:
match
is, in turn, an enhanced version of search
that lets you find multiple matches within a string according to a regular expression of your choice:
The replace
method lets you replace a piece of text with another one of your own choosing:
Since replace
also allows for regular expressions, you can match all occurrences of a substring and replace them at once. Just use the g
flag (which stands for global):
The substr
and substring
methods let you extract bits of text from an array by specifying indexes. The former expects the start index and the length of the substring whilst the latter expects the starting and ending indexes:
You can split a string in several pieces using the split
method. The resulting pieces of splitting the string are returned as items of an array:
The split
and join
methods make it dead easy to convert a string into an array and vice versa. Using them will allow you to take advantage of both the string and array methods without limitations. You have a string and want to use the Array.prototype.map
method? Convert it into an array via split
, perform whichever operations you need and then use join
to get your string back.
New String Features in ES6
ES6 brings a lot of exciting new features to strings:
- Several new helpful methods like
startsWith
andendsWith
. - A complete overhaul of how we define strings in JavaScript with Template Literals20. Template Literals provide a much better support for string interpolation, multiline strings, HTML-friendly strings and the ability to create reusable string formatters called tags.
ES6 Brings Some New String Methods
After reading the previous sections you may have missed three methods you often use in C#: Contains
, StartsWith
and EndsWith
. Well, worry no more because ES6 brings all these new methods to JavaScript strings:
The startsWith
and endsWith
methods work just like in C#. The first one verifies whether a string starts with a given substring and the latter checks whether or not a string ends with a given piece of text:
The includes
method performs the same function as C# Contains
by checking whether or not a piece of text is contained within a string:
Note how using the includes
method provides a much better developer experience and readable code than the indexOf
method from previous sections.
Finally, ES6 brings the repeat
method that allows you to create a new string by repeating an existing string a specific number of times:
The Awesomeness of ES6 Template Literals
ES6 template literals provide a new and very powerful way of working with strings. You can create a string using a template literal by wrapping some text between backticks:
Template literals let you use both single and double quotes freely without the need to escape them:
One of the greatest strengths of template literals is that you can inject values in a very straightforward and readable fashion. By using the notation ${target}
inside the template literal you can include the value of the variable target
in the resulting string. This is also known as string interpolation:
You can include any variable that is accessible within the scope where the template literal is declared. Say goodbye to concatenating strings and variables with the +
operator. Bye and farewell!
Additionally, you are not limited to using variables when doing string interpolation. You can use any valid JavaScript expression. For instance, you could call a function:
Or perform arithmetics:
Another great improvement from template literals over vanilla strings are multiline strings. With template literals, if you want to have a multiline string, you just write a multiline string. It’s that easy:
Tags
Tags are a very interesting feature of template literals. They allow you to customize how a specific template literal gets parsed into a string.
To apply a tag you prepend its name to the template literal:
In this example we have created a tag orcSpeech
to parse any piece of speech into the way orcs speak (who I’ve heard speak numerous times). When we evaluate the resulting string we can verify how the tag has transformed the original text into garbled orc speech:
How did that happen? Well, a tag is merely a function and what you see above is the result of calling that function with the string literal as input.
More specifically, a tag function takes each string literal of a template and each substitution (the ${}
tokens) and returns the parsed string after composing literals and substitution together:
In the previous example the literals
and substitutions
would be:
The implementation of the orcSpeech
tag function could look like this:
Where we compose literals and substitutions and then replace s
and r
with sss
and rr
respectively giving the original sentence that rough touch characteristic of orcs, goblins and other creatures of darkness.
When the tag is applied to a template literal like you saw above, the effect is the same as that of calling the tag function with the literals and substitutions. So this down here would be the same:
As calling orcSpeech
as a function:
In addition to what you’ve seen thus far, tags also give you the possibility to access the raw string literals. Having access to raw literals lets you customize even how you parse special characters such as end of line /n
, tabs /t
, etc.
We can illustrate this with an example of a hypothetical orcSpeechRaw
tag:
The literals
array exposes a raw
property that contains the same information than the literals
array but in raw format. If you take a look at the output of the non-raw tag orcSpeech
:
You’ll be able to appreciate how the special characters have been transformed into whitespace. If you then take a look at the output of the raw tag orcSpeechRaw
:
You’ll see how the special characters are available in the literals.raw
array.
In summary, tags give you the opportunity of creating reusable formatting functions or even small text manipulation DSL’s (Domain Specific Languages) for your web applications. For instance, an interesting application of tagged template literals could be building your own HTML templating engine:
Where we would create a ul
and li
tags that would be an extension over the more generic html
tag:
The code when applying the templating engine could be simplified further if we used ES6 arrow functions which we’ll cover in the next chapter. But there’s nothing preventing us from taking a sneak-peek right?
Beautiful!
String Cheatsheet
Basics
Basics | description |
---|---|
'a string' , "a string"
|
Create a string |
"Y'all" , 'the "laser" ` |
Escape single and double quotes |
"You are: " + status |
Concatenate strings and values using +
|
"lalalala too long" + |
Concatenate for multiline strings |
"lala" |
|
"lalalala too long\ |
Create multiline strings using \ at the end of each row |
lala" |
|
"this is\n a new line" |
Special characters start with \
|
String Methods
String Methods | description |
---|---|
concat(str1, str2, ...) |
Concatenate strings |
- "this is".concat(" excellent")
|
- "this is excellent"
|
toUpperCase() |
Uppercase all characters in a string |
- "abracadabra".toUpperCase()
|
- "ABRACADABRA"
|
toLowerCase() |
Lowercase all characters in a string |
- "SHAZAM!".toLowerCase()
|
- "shazam"
|
charAt(position) |
Get character at given position |
- "Just DO IT!".charAt(0)
|
- "J"
|
indexOf(string) |
Gets position of the first occurrence of a string |
- "JUST DO IT!".indexOf("DO")
|
- 5
|
search(regExp) |
Gets position of the first occurrence of a regular expression |
- "JUST DO IT!".search(/DO/)
|
|
match(regExp) |
Find strings matching a regex |
- "JUST DO IT!".search(/DO.*/)
|
- ['DO', 'DO IT']
|
`replace(str or regex, str) | Find and replace using a string or regex |
- "JUST DO IT!".replace('DO IT!', 'DANCE!')
|
- "JUST DANCE!"
|
split(separator) |
Separate string into an array of items using a separator |
- "JUST DO IT".split(" ")
|
- ["JUST", "DO", "IT"]
|
ES6 String Methods
String Methods | description |
---|---|
startsWith(str) |
Check whether a string starts with some text |
- "JUST DO IT".startsWith("JUST")
|
|
endsWith(str) |
Check whether a string ends with some text |
- "JUST DO IT".endsWith("IT")
|
|
includes(str) |
Check whether a string contains some text |
- "JUST DO IT".includes("DO")
|
|
repeat(times) |
Create a new string by repeating the current string N times |
- "Na".repeat(3)
|
- "NaNaNa"
|
ES6 Template Literals
Template Literals | description |
---|---|
`new literal` |
Create template literal |
- "new literal"
|
|
`I have ${coins} coins` |
Variable interpolation |
- "I have 10 coints"
|
|
`I have ${1+1} coins` |
Evaluate expressions |
- "I have 2 coins"
|
|
li`purse` |
Use of tags |
- "<li>purse</li>"
|
Concluding
And we got to the end! In this chapter you learned a ton about strings in JavaScript, you saw how strings are a primitive type which behave in a very similar way to C# strings. They are immutable and performing operations on them or changing them in some fashion results in a new string being created.
Strings behave like array-like objects and although they don’t have array methods, you can apply the non-destructive array methods on them by virtue of using call
and apply
. In addition to this, strings have a lot of methods that you can use to perform operations like concatenation, matching, searching, extracting and replacing pieces of text.
ES6 brings new string methods like startsWith
and endsWith
but more importantly it comes with a new way to work with strings in the form of template literals. Template literals are a great improvement over vanilla strings because they let you inject values within strings in a very straightforward fashion and make creating multiline strings seamless. Tags are a great companion to template literals that let you customize how a template literal is parsed into a string opening an endless world of possibilities when it comes to text manipulation in JavaScript.
Exercises
Upgrading Your Everyday JavaScript Magic With ES6 - Destructuring
There's always a better way to solve a problem You just haven't found it... ...yet - Torvik Knivsa Alchemist
Welcome to the Future! ECMAScript 6
Welcome back JavaScriptmancer! So far in this first part of the book you’ve seen several great ES6 features:
- In The Basics Of JavaScript Functions you learned about the new
let
andconst
keyword that let you declare block scoped variables. - In Useful Function Patterns: Default Parameters you saw how ES6 brings default parameters to JavaScript. They have a very similar syntax to C# and let you use any valid expression as a default value, even objects and functions.
- In Useful Function Patterns: Multiple Arguments you found out about rest parameters. They work just like C#
params
and let you define functions that take an arbitrary number of arguments. - In On the Art of Summoning Servants and Critters, Or Understanding The Basics of JavaScript Objects you discovered how ES6 simplifies object initializers with the shorthand syntax (both for properties and methods). You also learned about ES6 symbols and how they can help you with data privacy.
- In A Guide to Strings, Finding the Right Words and Proper Spell Intonation you dived into ES6 Template Literals and learned how they revolutionize the way we work with strings in JavaScript. You also took a look at tags and the new string methods.
In this and the upcoming chapters we will introduce other great ES6 features that you can use in your everyday JavaScript: destructuring, arrow functions and the spread operator. It’s time to upgrade your JavaScript wizardry to ES6!
Destructure All The Things!
ES6 comes with a very handy new feature called destructuring. Destructuring lets you extract parts of information from within objects and other data structures in a very natural and concise manner.
Destructuring Objects
In the simplest of use cases, you can initialize variables from properties of objects using the following syntax:
This is equivalent to:
Using destructuring in a real world example is not very different. Imagine that you have a cimmerian barbarian that is yearning to improve his JavaScript skills. Let’s call him conan
:
We can create a javascriptmancyCourse
object that allows anyone, not just barbarians, to learn some javascript by using a helpful signUp
method:
The let {firstName, lastName} = conan
lets us extract the information necessary from the conan
object and have it ready for processing in a terse single statement. If you appreciate writing beautiful code it doesn’t get better than this.
And there’s more! You are not limited to using variables that have exactly the same names than the properties within the original object. You can take advantage of a slightly more advanced destructuring syntax to map an object property to a different variable:
This is equivalent to:
So that lastName
is the name of the origin property and title
is the name of the destination variable. Additionally, if you try to extract a property that doesn’t exist in the source object, the newly created variable will be undefined
:
To prevent this from happening you can use default values in tandem with destructuring syntax. With this powerful combination, if an object doesn’t have a given property, your variable still gets a default value instead of undefined
.
Using defaults with destructuring as depicted above will ensure that you’ll never be poor and enjoy those illusory 10
bills even when they are not in your pouch
. Magic!
Yet another mighty feature of destructuring is the ability to extract properties that are deep within an object. Imagine that you have one of those useful bags that have infinite pockets and you want to reach for your tobacco pouch:
Well you can create a new tobbacoPouch
variable using destructuring. It’s this easy:
You can read this like go into the leftPocket
grab the tobaccoPouch
and put it in its own separate variable.
Again if the property you are trying to extract doesn’t exist you’ll get undefined
:
But beware, because if there is a missing property in the object graph on the way to the specific property you want, the destructuring will result in a SyntaxError
:
In this previous example the centralPocket
property doesn’t exist in the bag
object. This means that the JavaScript runtime cannot traverse the object to get to the superSecretPouch
and thus you get the SyntaxError
as a result.
And now that we’re talking about errors and problems, let’s take a look at something that you cannot do with destructuring, something that has bitten me repeatedly: Extracting a property into an existing variable. No, this here won’t work:
Yes, I know… But don’t be sad. The happy news is that you can also use all you’ve learned thus far with arrays! Wiii! Let’s destructure!
Destructuring Arrays
Destructuring arrays is just as easy as destructuring objects. Instead of using curly braces {}
though, you’ll use the more familiar array square brackets []
:
In this example you see how we extract the first three elements of the array and place them in three distinct variables: one
, two
and three
. The fourth element in the array, the scary white walker
remains unreferenced by any variable.
You can also jump places within the array:
Destructuring arrays comes very handy when you want to get the first element of an array in a very readable and intuitive fashion:
Which you can combine with the rest operator like this:
Unfortunately this trick doesn’t work for the last element of the array because the rest operator is greedy. It wants to extract all items in the array and therefore [...initialOnes, last]
wouldn’t do the job.
You could be a super crafty fox and do the following:
Beautiful21! Another use case for array destructuring is to swap the values of two variables:
Finally, you can enjoy the versatile defaults when performing array destructuring as well:
Because we try to extract three elements from an array that only has two the yetAnotherMonster
variable would get a value of undefined
. The use of a default prevents that and ensures that the variable has a safe value of cucumber
. Because nothing speaks of safety like a cucumber.
Destructuring Function Arguments
In Useful Function Patterns: Default Parameters you briefly saw how destructuring can be useful when used within the parameter list of a function.
The principle is the same but the destructuring process happens in a more indirect fashion. One piece of the destructuring is the object being passed as an argument to a method, in this case options
:
And the other bit is the destructuring syntax with the specific variables as part of the method signature {direction}
:
Just like normal destructuring it also works with arrays:
And you can use any of the features you’ve learned in this section for both object and array parameters: defaults, nested properties, jumping over array items, etc.
Concluding
In this chapter we did a brief review of all the ES6 features that you’ve learned so far: let
, const
for block scoped variables, default parameters, rest parameters which work like C# params
, shorthand syntax for object initializers, symbols, template literals, tags and the new string methods.
We also dived deeper into destructuring and learned how you can use this new feature to easily extract properties from objects and items from arrays. You discovered that you can use destructuring within the arguments of a function and how to combine destructuring and default values when the property you are trying to extract doesn’t exist within an object or array.
Exercises
Upgrading Your Everyday JavaScript Magic With ES6 - Arrow Functions
Speak less. That way there's less chance that you'll say something stupid. Think about that, when you craft your next spell. - Kyeich Chir Guardian of the word
Behold! The Arrow Function!
Arrow functions are one of my favorite features in ES6. They give you a beautiful and terse way to write JavaScript functions which is reminiscent of C# lambda expressions.
Here you have a vanilla JavaScript function expression:
And here you have an equivalent version as an arrow function:
If you call any of these functions you’ll get the same result:
Let’s examine the arrow function in closer quarters. You may have noticed that it doesn’t have any return
statement. And that’s because in its simplest incarnation, the arrow function has an implicit return
that returns whichever expression is to the right of the fat arrow =>
. Note that this notation is only valid when an arrow function has a single statement.
Like in C#, you’ll often see arrow functions used in conjunction with array methods such as filter
(the JavaScript version of LINQ’s Where
):
You can define arrow functions with any arbitrary number of arguments. For instance, you can have no arguments at all:
Or one:
Two:
Or as many arguments as you want using the rest syntax:
Because they are just functions you can also use defaults:
And destructuring:
If the body of your arrow function has more than one statement then you’ll need to wrap it inside curly braces just like you would do in C#:
Additionally, when you have more than one statement you’ll need to return
a value explicitly:
An arrow function can also return an object via the object initializer syntax. When doing so, you’ll need to wrap it inside parentheses. That way the JavaScript runtime will be able to understand that it is an object and not a block of code:
In summary, arrow functions are awesome. Using arrow functions you’ll be able to write much terser code and still get to use features like destructuring or defaults. But as functions themselves they are a little bit special, and when I say a little I mean a lot.
Arrow Functions Arcana
Indeed, though they seem like regular functions, arrow functions have their quirks:
- They don’t have
this
- They don’t have an
arguments
object - You cannot use
bind
,apply
andcall
to set the context in which they are evaluated - You cannot use
new
norsuper
This may be surprising but if you take a look at the ECMA-262 specification22, that is, JavaScript’s own specification, you’ll read the following:
14.2.16 Arrow Functions - Runtime Semantics: Evaluation
An ArrowFunction does not define local bindings for
arguments
,super
,this
, ornew.target
. Any reference toarguments
,super
,this
, ornew.target
within an ArrowFunction must resolve to a binding in a lexically enclosing environment. Typically this will be the Function Environment of an immediately enclosing function.
But what does it exactly mean for arrow functions not to have their own version of this
nor arguments
?
It means that when you refer to this
or arguments
within an arrow function you are actually referring to this
or arguments
in the enclosing environment. Let’s clarify this with an example.
Let’s say that we have gollum
that wants to be pleasant to you just before he stabs you in the back and steals your wedding ring. If we use normal functions to define his greetings:
And then call the function saysHi
:
As we expected, gollum
happily salutes us. Then, after a short while, he returns and stabs us in the back. The only problem being that it is no longer gollum
but the Window
object. This is nothing new. We learned about this strange behavior of this
in Mysteries of the JavaScript Arcana. But what happens if we use an arrow function instead of a normal function?
Notice how we have rewritten the saysHi
function to use an arrow function within setTimeout
instead of a normal function. If we call it:
The arrow function guarantees that the right version of this
is used. What is happening? Because the arrow function doesn’t have its own version of this
it accesses the this
defined by the saysHi
method (effectively behaving like a closure). Because saysHi
was called using the dot notation gollumWithArrowFunctions.saysHi
then the object itself is the value of this
and thus everything works yey! And we die an ignominious death at Gollum’s hands. No!
What are the consequences of this? Well, the most exciting consequence of an arrow function not having its own this
is that it makes them more resistant to the this
problems you saw in Mysteries of the JavaScript Arcana (they are more resistant but not bullet proof as you’ll see later in this chapter).
Let’s bring this concept home with another example, the same one we used in Mysteries of the JavaScript Arcana:
Again, if you take advantage of arrow functions and substitute the updateUsers
function expression for an arrow function you’ll solve the problem. And in a more elegant way than binding the function explicitly (with bind
) or using a closure (var self = this
). You can appreciate that elegance in this example below:
Arrow Functions And This Gotchas
Now that we’ve learned about the good parts of the arrow function and how it can help us write terser code and avoid some problems with the this
keyword let’s take a look at its darker sides: when an arrow function doesn’t behave like a function.
Let’s start with the not having this
and when it can become a problem.
Beware of Using Arrow Functions With Object Literals
My first thought when I learned about arrow functions was: Awesome! Now I can use arrow functions everywhere! And so I wrote this:
To my surprise, when I tried to have raistlin
cast an evil death ray this is what happened:
The arrow function, which we had thought impervious to this
problems before, now reveals us the classic this
issue.
What is happening here? Well, if you remember from the previous section arrow functions don’t have this
. Because of that, when you try to access this
inside an arrow function you’re referring to the this
of the outer scope. In the case of an object literal, the this
from the outer scope is no other than the Window
object. Again, the rules we learned about this
in Mysteries of the JavaScript Arcana don’t apply to arrow functions and calling an arrow function using the dot notation doesn’t evaluate it in the context of the object. So remember, be wary of using arrow functions as properties of object literals.
You Can’t Bind Arrow Functions
You cannot use bind
with arrow functions. If you are brave enough to try to bind an arrow function to an object you’ll be sorely disappointed because it won’t work.
Let’s illustrate it with an example:
Behold saruman
! Another epic javascriptmancer. He has a couple of methods that show his magic prowess. One raiseUrukhai
is a regular function, the other telekineticStaffAttack
uses an arrow function. If we call these methods using the dot notation:
Again, just like we saw in the previous section, when we call telekineticStaffAttack
method the this
gets evaluated as Window
. But let’s say that we want to solve it as we are accustomed to by using bind
.
If we use bind
to bind these two methods to a different object:
We can appreciate how we can bind a normal function but when we try to bind an arrow function nothing happens:
Since an arrow function doesn’t have this
it makes no sense to bind
it.
Even though arrow functions are not the same as bound functions, once an arrow function is declared and encloses its nearest this
it pretty much behaves in the same way as a bound function. Let’s illustrate this idea with some code:
In this example we are using a constructor function and the new keyword to instantiate a fiery warg. Even though we haven’t seen any of these concepts yet because I am reserving them for the OOP section of the series, they are still the best way to exemplify the similar behavior of arrow functions and bound functions (I hope you’ll forgive me).
Essentially you use the new
keyword to instantiate new objects via constructor functions. When you apply the new keyword on any function the JavaScript runtime instantiates an object {}
, sets it as the this
value of the function, then evaluates the function and finally returns it. This is useful because it is the this
value that the wark
method is going to enclose and safeguard for the rest of the program execution.
After creating willyTheWarg
we got ourselves an arrow function wark
and a bound function jump
. If we execute any of them we will be able to appreciate how this
refers to the warg itself:
This is the expected behavior, but what happens if we are mean and take these functions away from willyTheWarg
?
Well the bound function, as we learned in Mysteries of the JavaScript Arcana, will still have willyTheWarg
as its context:
And the arrow function behaves in exact the same way. Instead of being explicitely bound to willyTheWarg
it is implicitly bound by the closure over the this
variable:
This similar behavior and the fact that neither bound nor arrow functions can be bound (re-bound in the case of the bound function) makes both types of function practically identical in this situation. The only difference being that bound functions don’t need a closure, you can just bind a normal function to whatever object you want by just calling the bind
method. Arrow functions, on the other hand, can be seen to be implicitly bound to their enclosing context by virtue of the closure.
You Can’t Use Apply or Call on Arrow Functions
In addition to bind
, you cannot use call
nor apply
on an arrow function to change its context. If you remember Mysteries of the JavaScript Arcana, you can use call
and apply
to explicitly set the context in which a function is executed, that is, the value of this
:
But if you try to use either apply
or call
with an arrow function, the context that you pass as argument will be completely ignored:
In the example above you can easily appreciate how instead of scary caragor
the ${this}
within the wark
arrow function is evaluated as willy, the little
. This demostrates how arrow functions ignore the context when called with either call
or apply
.
Arrow Functions Don’t Have Arguments Object
Another interesting feature of arrow functions is that they don’t have arguments
object. Just like with this
if you attempt to access the arguments
object within an arrow function you’ll access the arguments
of the enclosing environment.
If you remember More Useful Function Patterns - Multiple Arguments every function in JavaScript has a arguments
object that you can use to access which arguments where passed to a function. So if you have a normal function that logs the arguments
object:
You can easily demonstrate how the arguments
object collects those arguments being passed to the function:
Not so with arrow functions:
The arguments
variable is not defined and thus we get a ReferenceError
. Let’s define it and see what happens:
We can also make the same experiment wrapping an arrow function inside another function:
So as you can see in both these examples, arrow functions don’t have their own arguments
object and use the arguments
object of their enclosing environment. But What if we want to send an arbitrary number or arguments to an arrow function? Well, in that case you should use the rest operator:
In summary, whenever you use arguments
inside an arrow function you’ll be accessing the enclosing environment’s arguments
object. So if you want to send multiple arbitrary arguments to an arrow function use the rest operator.
Arrow Functions and the New and Super Operators
The new
and super
operators are two operators that we will see in depth in the OOP section of the series. The new
operator lets you create new instances of objects when applied to any function which will then act as a constructor. The super
keyword is new in ES6 and lets you access methods in parent classes within an inheritance chain.
In much the same way as with bind
, call
and apply
, you cannot use new
nor super
with an arrow function.
Concluding
In this chapter you learned about ES6 arrow functions which resemble lambdas in C#. Arrow functions let you use a terser syntax than the normal function syntax and help you avoid problems with the this
keyword by using the this
value of their enclosing environment.
Arrow functions are a little bit special in what regards to this
since they are the only functions in JavaScript that don’t have their own this
value. Because of this characteristic you cannot use bind
, call
or apply
to specify the context in which an arrow function will be evaluated. In a similar fashion you cannot use the new
and super
operators with an arrow function.
Additionally, arrow functions don’t have their own arguments
object, if you try to access arguments
inside an arrow function you’ll access the arguments
object within the enclosing function. This means that if you want for an arrow function to take an arbitrary number of arguments you’ll need to use the rest syntax.
Exercises
Upgrading Your Everyday JavaScript Magic With ES6 - The Spread Operator
Learn to recognize beauty in code, it will make the task of coding a pleasure in itself, it will make you appreciate code in a whole different way. - Zazongel emjia Bard and Poet
Ready To Spread Your Wings?
In More Useful Function Patterns: Multiple Arguments you learned about rest parameters, a new ES6 feature, that lets you define functions with an arbitrary number of arguments just like params
in C#.
The spread operator works sort of in an opposite way to the rest operator. Where the rest operator takes a variable number of arguments and packs them into an array, the spread operator takes and array and expands it into its compounding items.
In this chapter you’ll see several recipes that will help you write better code by taking advantage of the spread operator like, for instance, concatenating arrays.
Use the Spread Operator to Seamlessly Concatenate Arrays
You can use the spread operator to easily concatenate arrays with each other. Let’s say that we want to collect our most terrible enemies for later reference. We have an array knownFoesLevel1
and another array newFoes
with newly acquired enemies (because you can never have enough enemies):
Since it’s easier to manage one collection than two, we want to merge these two collections into one single array. Where you would have used the concat
method in ES5:
In ES6 you can use the spread operator to achieve the same result with a much clearer syntax:
You can even mix arrays and singular items:
Easily Use Apply With the Spread Operator
Another useful use case of the spread operator is as an alternative syntax to Function.prototype.apply
.
In Mysteries of the JavaScript Arcana you learned about how you can use the apply
function to explicitly set the context (this
) in which a function is executed. You also learned how apply
expects an array of arguments as second parameter and how when the function is finally invoked each element within the array is passed as a separate argument to the original function.
Well the spread operator let’s you call an arbitrary function with an array of arguments in a better way than apply
does.
Let’s say that you are working on a spell to command your minions with random actions because being too predictive is boring and you appreciate the wild factor. You express these random actions as arrays: ['minion1', 'action', 'minion2']
Now let’s say that you have a function of your own device where you want actions to be done viciously (looks like you are in a foul mood today):
Because the action is expressed as an array but the performActionViciously
function expects a separate series of arguments you need a way to adapt these two disparate elements.
Prior to ES6 you would have used the apply
function:
Where you would need to fill in the context in which the function will be executed for the apply
method to work (that is, the value of this
).
With ES6 you can use the spread operator to easily perform an action:
No need to set the context in which the function is executed and the resulting code is much concise with the omission of apply
.
Now you may be asking yourself: Why don’t I make the performActionViciously
function take an array as argument and forget all this spread operator nonsense? Well, you could do that. But what happens when you have no control over the function being called?
Take console.log
. Imagine that, instead of performing these actions viciously, you just want to log them. Because console.log
takes an arbitrary number of arguments and you have an array, you need some way to adapt the array to the expected signature. Again, prior to ES6 you would use apply
:
With ES6 and the spread operator you can simplify the code sample above greatly:
Another example in which the spread operator comes handy is when we want to extend an existing array with another array. In the olden days we would have written:
With the spread operator it’s as easy as:
In summary, do you have some variable as an array and need to apply it to a function that takes separate arguments? Use the spread operator.
Converting Array-likes and Collections Into Arrays
Another interesting application of the spread operator is to convert array-like objects into arrays.
If you remember More Useful Function Patterns: Multiple Arguments, array-like objects are a special type of object that can be indexed, enumerated, has a length property but doesn’t have any of the methods of an array. Some examples of array-like objects are the arguments
object inside functions or the list of DOM23 nodes that result when using document.querySelector
.
Let’s imagine that we have a web-based user interface, a form, to help us create minions based on some characteristics that we can type manually (for even wizards can benefit from web interfaces). It could look like this:
When you click on the Save
button we want to store these values and create a new minion that will serve us for eternity. So we add an event handler saveMinion
that will be called when the form is submitted:
In the example above we use the document.querySelector
method to select the form element that represents the actual form on the web page. After that, we call the addEventListener
method to register a saveMinion
event handler for the submit event of the form. Whenever the user clicks on the Save
button, the form will be submitted and the saveMinion
method will be called.
The next step would be to extract the values from the inputs above. How can we go about that? Well, we can select all the inputs within the form and extract the values that we or another wizards have typed in.
So we use the form.querySelectorAll('input')
method to select all input elements within the form. This method returns an array-like object of nodes. Because it has a length property we can use a simple for loop and a new array values
to collect the values. After that we can create our brand new minion with the extracted values.
But, is there a better way to collect these values? What about converting the inputs
array-like object to an array and using the helpful array methods instead of the for loop? Spread operator to the rescue!
By converting the array-like to an array using the spread operator we can use array functions such as map
and write more beautiful code! map
works just like LINQ’s Select
and let’s you perform transformations on each item of a collection. In this case we just transform a collection of elements into values. Awesome right?
In addition to array-like objects you can use the spread operator to convert any iterable object to an array. For instance a Set
(a collection of unique items):
Or a Map
(like a C# Dictionary
):
Spread Lets You Combine New and Apply
The spread operator also lets you combine the new
operator with the ability to apply
arguments to a function. That is, the ability to instantiate objects using a constructor function while, at the same time, adapting an array of arguments into a constructor function that expects separate arguments.
Let’s continue the example from the previous section where we extracted the characteristics of our minion from an HTML form. To refresh your memory the form looked like this:
The next natural step would be to create a new minion using those characteristics and the following constructor function:
If we were to use pure ES5 we would need to unwrap the values before we use them:
With ES6 we can combine new
with the spread operator to get this beautiful piece of code:
The full code example could look like this:
In the example above we first extract the values from the form and then we use them to create a newMinion
object by applying both the new
and the spread operators at once.
Concluding
In this chapter you learned about the ES6 spread operator and how it works in sort of the opposite way to the rest operator. Instead of grouping separate items into an array, the spread operator expands arrays into separate items.
You learned how you can use it in many scenarios usually resulting in more readable code: to easily concatenate arrays, as a substitute for apply
, to convert array-like objects and even other iterables to arrays and, finally, to combine the new
operator with apply
.
This chapter wraps the first tome of JavaScriptmancy! Great job JavaScriptmancer! Time to spread your wings and dive into the mysteries of data structures in JavaScript!
Exercises
Tome I.II JavaScriptmancy and Data Structures
JavaScript Arrays: The All-in-one Data Structure
Remember, Grasp the subject, and the words will follow. Have the argument clear in your mind, and the words will flow naturally. Focus on the data structures first, and your code will be cleaner. - Svotarld Siunl Sage
We’ll Just Need To Make Sense of All These Items
For a very long time (up until the year 2015 and the advent of ES6) the only data structure available in JavaScript was the array. This was not a big problem for the hordes of JavaScript developers because JavaScript’s array is an array, a list, a queue, a stack and, in addition, provides similar functionality to LINQ. Sounds interesting? Let’s have a look.
JavaScript’s Array
The easiest way to create an array in JavaScript is to use the array literal:
Although you can use the Array constructor as well:
Which unfortunately is a little bit inconsistent. For instance, you can use the Array
constructor with one single argument to create an array of an arbitrary size:
Or you can use it with more than one argument to create an array that will contain the arguments that you pass in (just like []
):
As you would expect from any array worth its salt, you can set items in the array by index:
And you can also retrieve these items by indexing the array:
Arrays have a dynamic size and they grow as you add new elements to them. You can access the size of an array using its length
property:
Specially interesting is the fact that JavaScript allows you to have elements of disparate types within the same array:
An Extremely Flexible Data Structure
The Array was the sole data structure available in JavaScript for a long time and, as such, it grew to provide a lot of functionality to cover most of the use cases that you usually run into when writing JavaScript applications. It is somewhat of an all-purpose collection.
For instance, it can work as a stack (LIFO - Last In First Out) if you use the methods push
and pop
. These methods add and remove elements from the end of the array respectively:
It can work as a queue (FIFO - First In First Out) if you use the method shift
to extract an item from the beginning of the array and combine it with push
:
You can also insert items in the beginning of the array by using the unshift
method:
Additionally, both push
and unshift
let you add multiple items at once:
Another useful method that lets you remove items from any arbitrary position of an array is the splice
method. It has many use cases:
splice
can even insert items at a given point:
or remove items and insert items at once:
Sorting Arrays
Arrays offer a couple of methods that let you sort the elements they contain. The first one that you need to consider is the sort
method which takes a comparing function as argument. Let’s sort our potions:
And it looks like you need to buy some more of that curing poison because you never know what may be waiting to bite you behind that next corner. The comparing function compare(a,b)
is expected to return:
-
0
whena
andb
are considered equal -
< 0
whena < b
-
> 0
whena > b
Another fact that is important to remember is that the sort
method does in-place sorting so your original array will reflect the changes after being sorted.
The second array method related to sorting is the reverse
method. This method reverses the position of all items within the array and does so in-place:
Safe Array Methods
All these methods that we have seen up until now mutate the array itself. This means that using them will change the inner contents of the array where the method is called. Let’s look at some safe methods now, methods that don’t change the original array.
The concat
method lets you concatenate two arrays together and returns the resulting array:
The join
method allows you to join the elements of an array to form a string using an arbitrary separator of your choice:
The indexOf
method returns the position of an item within an array:
It is often used to find out whether or not an array contains a given item like this:
indexOf
returns the first ocurrence of an item in an array, alternatively you can use lastIndexOf
to find the last ocurrence of an item.
The last safe array method is slice
which is a non-destructive alternative to splice
. This being JavaScript we couldn’t have a similar signature. Instead of working with the start index and the number of items to remove, the slice
method expects the start
and end
of the subarray to extract:
slice
also supports negative indices which represent starting counting from the end of the array. The end
parameters is also optional, so we can extract a new array containing only the last item from the original array pretty easily:
Iterating an array
Prior to ES6, JavaScript offered two ways in which to iterate over the elements of an array: the for/in
loop and the Array.prototype.forEach
method.
The for/in
loop is a JavaScript construct that lets you iterate over the properties1 of any object. In the case of an array, these properties are the indices of the array:
The forEach
method offers a better developer experience to iterating as it gives you each item of the array directly:
And, additionally, it gives you access to each index
and the array
itself:
ES6 generalizes the concept of iterability in JavaScript through the addition of the iterator protocol and the for/of
loop:
JavaScript Arrays and LINQ
If you thought that everything you’ve seen thus far was everything there was about JavaScript arrays you’re in for a treat, because Wait! There is more!.
One of my favorites features of the JavaScript array is that it comes with a set of methods that are very similar to .NET LINQ. Yes, you read it. Isn’t that absolutely awesome? I devote a whole chapter to the Array’s LINQ-like methods in the functional programming tome of this series, but here’s a small appetizer.
I used arrow functions in this example to give you a feeling of familiarity between the Array.prototype
LINQ-like methods and LINQ, but you must know that most of these methods are available in ES5 and work just as well with normal function expressions.
Other ES6 and ES7 Features
In addition to formalizing the concept of iteration in Arrays, ES6 brings several new helpful methods that will make operating on Arrays and Array-likes easier.
The Array.from
method let’s you create an array from any array-like
and iterable object. It is ES6’s solution to the commonplace practice of using Array.prototype.slice
in ES5 to convert array-likes into proper arrays:
Any object that can be iterated over can be converted into an array using Array.from
. For instance, a Map
:
Array.from
also takes a second optional argument, a map
function that just like LINQ’s Select
let’s you transform each element within the source array into something else of your own choosing:
The Array.isArray
method provides a more convenient and safer 2 way to check whether an object is an array or not. Prior to ES6 we used to use the following approach:
With Array.isArray
it’s more straightforward:
The Array.of
method lets you create an array from a variable number of arguments and is equivalent to []
:
Why would you want to use Array.of
instead of []
then? There is a corner case application where Array.of
is essential, when creating Array subclasses:
Array.prototype.copyWithin()
provides a way to copy items within the same array, that is, pick a portion of an array and copy it within the same array. Let’s illustrate it with an example:
Array.prototype.fill()
provides a convenient way to fill an existing array with a specific item:
New Array methods in ES7
ES7, while being a very small incremental release of JavaScript, brings a very convenient way to check whether an item exists within an array, the Array.prototype.includes()
method:
This provides a much better developer experience than the indexOf
method that we saw previously in this chapter:
In addition to providing which item within the array you are looking for, you can specify an starting index for the search:
Array Cheatsheet
Basics | description |
---|---|
[] |
Create an empty array |
[1, 2, 3] |
Create an array |
Array(n) |
Create array with n undefined elements |
Array(1, 2, 3) |
Equivalent to [1, 2, 3]
|
Array Unsafe Methods ES5
method name | superpower |
---|---|
Array.prototype.push(n1, n2...) |
Append item to the end of an array |
- [].push(1)
|
|
- [].push(1, 2, 3)
|
|
Array.prototype.pop() |
Remove item from the end of an array |
- let n = [1].pop()
|
|
Array.prototype.shift() |
Remove item from the beginning of an array |
- let n = [1].shift()
|
|
Array.prototype.unshift(n1, n2...) |
Insert item to the beginning of an array |
- [].unshift(1)
|
|
- [].unshift(1, 2, 3)
|
|
Array.prototype.splice(start, length, n1, n2) |
Remove items from any arbitrary position and insert new ones |
- [1,2].splice(0, 1)
|
- remove first item |
- [1,2].splice(-1, 1)
|
- remove last item |
- [1,2,3,4].splice(1,2)
|
- remove two items in the middle |
- [1,2].splice(0, 1, 'ash')
|
- change first item for 'ash'
|
- [1,2,3,4].splice(1,2, 'ash', 'gold')
|
- change two middle items from 'ash' and 'gold'
|
Array.prototype.sort(compareFn) |
Sort array |
- [1,2,3].sort()
|
- sort according to character UNICODE code point value |
- [1,2,3].sort((a,b) => a-b)
|
- sort numbers |
- a > b ⇒ return > 0 | |
- a < b ⇒ return < 0 | |
- a === b ⇒ return 0 | |
Array.prototype.reverse() |
Reverse order of items within an array |
- [1,2,3].reverse()
|
Array Safe Methods ES5
method name | superpower |
---|---|
Array.prototype.concat(arr) |
Concatenates two arrays |
- [1,2,3].concat([5,6])
|
|
Array.prototype.join(separator) |
Join items of the array using a separator
|
- [1,2,3].join(', ')
|
- "1, 2, 3"
|
Array.prototype.indexOf(n) |
Returns index of the first ocurrence of an item within an array |
- [1,2,3].indexOf(1)
|
|
- [1,2,3].indexOf(55)
|
- returns -1 if the item is not in the array |
Array.prototype.lastIndexOf(n) |
Returns index of the last ocurrence of an item within an array |
- [1,1,1].lastIndexOf(1)
|
|
- [1,1,1].lastIndexOf(22)
|
- returns -1 if the item is not in the array |
Array.prototype.slice(start, end) |
Returns subarray between start and end indexes. end indexed item is not included. |
- [1,2,3].slice(1,2)
|
- returns [2]
|
- [1,2,3].slice(1)
|
- returns [2, 3]
|
- [1,2,3].slice(-1)
|
- returns [3]
|
Iterating Arrays
method | superpower |
---|---|
for/in loop |
Loops over the indexes of an array |
- for(var i in arr)
|
|
for/of loop |
Loops over the items of an array |
- for(let i of arr)
|
|
Array.prototype.forEach |
Loops over the items of an array |
- arr.forEach(doSomething)
|
Array LINQ-like Methods
- See to Chapter LINQ chapter in the Functional Programming Tome of the Series.
New Array Methods in ES6
method name | superpower |
---|---|
Array.from |
Convert any iterable in an array. Also works on array-likes. |
- Array.from(arguments)
|
|
Array.isArray(obj) |
Check whether an object is an array. |
- Array.isArray([1,2,3])
|
|
Array.prototype.of() |
Instantiate a new array. Useful when subclassing Array
|
- MyArray.of(1,2,3)
|
|
Array.prototype.copyWithin(target, start, end) |
Copy array subset in place, that is, within the same array. |
- [1,2,3].copyWithin(0, 1, 2)
|
- [2,2,3]
|
Array.prototype.fill(item, start, end) |
Fill array with items |
- [1,2,3].fill(1)
|
-[1,1,1]
|
- [1,2,3].fill(1,2)
|
-[1,2,1]
|
- [1,2,3].fill(1,1,2)
|
-[1,1,3]
|
ES7
method name | superpower |
---|---|
Array.prototype.includes(item, start) |
Check whether an array contains an item
|
- [1,1,1].includes(2)
|
Concluding
JavaScript’s array is an all-purpose collection, a extremely and versatile data structure that will cover most of you application needs. You can use it as a stack, a queue, a list, you can easily perform destructive and non-destructive operations on it. It also has support for LINQ-like functionality that will make working with collections of items a breeze.
Even though JavaScript’s array is awesome, there’s a couple of use cases that are best suited for other data structures: storing items by an arbitrary key and managing collections of unique items. And that’s what we will learn in the next two chapters since both Maps
(like a Dictionary<T,T>
) and Sets
are two new data structures available from ES6 onwards.
Exercises
Organizing Your Data With ES6 Maps
It is unknown who designed the first map. But it is said that he got tired of traversing a whole array of shoes every time he decided to go for a walk. - Ckor Srich Royal Buffoon 2nd Age
Take a Look at These Maps
ES6 brings two new data structures to JavaScript, the Map
and the Set
. This chapter is devoted to the Map
, which is fundamentally a HashTable
. We often refer to it as Dictionary
in C#. JavaScript’s Map
provides a simple API to store objects by an arbitrary key, a very essential functionality required in many JavaScript programs.
JavaScript’s Map
You can create a Map
in JavaScript using the new operator:
Once created the Map
offers two fundamental methods: get
and set
. As you can probably guess using your wizardy intuition, you use set
to add an object to the Map
:
And get
to retrieve it:
This being JavaScript you can use any type as key or value, and the same Map
can hold disparate types for both keys and values. Yey! Freedom!:
You can easily find how many elements are stored within a Map
using the size
property:
Removing items from a Map
is very straightforward as well, you use the delete
method with the item’s key. Let’s do some cleanup and remove those nonsensical items from the last example:
Now that we have removed them, we can verify that indeed they are gone using the has
method:
And when we are done for the day and want to remove every item at once, the Map
offers the clear
method:
Iterating Over the Elements of a Map
Just like with arrays you can iterate over the elements of a Map
using the for/of
loop:
The default Map
iterator (also available via the entries
property) lets you traverse a Map
using key-value pairs. Each pair is an array with two items, the first being the key and the second the value. The example above is equivalent to:
Both examples above are a little displeasing to the eye, aren’t they? You can improve them greatly if you use the destructuring syntax to extract the key and the value from the key-value array:
Much nicer right? Alternatively you can use the Map.prototype.forEach
method analogous to Array.prototype.forEach
but with keys and values:
In addition to iterating over key-value pairs, you can also traverse the keys
:
And the values
:
Both the keys
and values
iterators provide a better developer experience in those cases where you just need the keys or the values.
Note that in the examples above we created an Array
from the keys
and the values
iterators and concatenated its elements using join
. This resulted in us “iterating” over the whole Map
at once, but we could have just as well used a for/of
loop and operated on each item separately.
Creating a Map From an Iterable Collection
In addition to creating empty Maps and filling them with information, you can create Maps from any iterable collection. For instance, let’s say that you have an array of wizards:
And you want to group them by race
and put them on a dictionary where you can easily find them. You can do that by passing a suitably shaped collection into the Map
constructor:
The Map
constructor expects to find an iterator that goes through key-value pairs represented as an array where the first element is the key and the second element is the value:
In the example above we used map
over the wizards
array to transform each element of the original array into a new one that represents key-value pairs, which are the race of the wizard and the wizard itself.
We could create a helper method toKeyValue
to make this transformation easier:
The toKeyValue
function above is a generator, a special function that helps you build iterators. You’ll learn more about generators later in this tome on data structures. For the time being, you just need to understand that we are transforming each element of an array into a key value pair.
When we call the generator we effectively transform the array into an iterator of key value pairs:
We can pass this new iterator to the to the Map
constructor and obtain the desired Map
of wizards:
We still need to perform the transformation in two separate steps which is not very developer friendly. We can improve this by extending the Array.prototype
with a toKeyValue
method:
This would allow you to rewrite the previous example like this:
You could even bring it one step further by creating a toMap
function:
Map Cheatsheet
Basic Operations
Basics | description |
---|---|
var map = new Map() | Create an empty map |
var map = new Map(iterator) | Create a map from an iterator |
var value = map.get(‘key’) | Get a value from the map by key. If the key is not in the map it returns undefined. The key can be of any type. |
map.set(‘key’, ‘value’) | Add an item to the map. If the key already exists within the map the value is overwritten. The key and value can be of any type. Chainable. |
map.delete(‘key’) | Remove item by key if it exists. Returns true if an item has been removed and false otherwise. |
map.has(‘key’) | Check whether a key exists in the map. Returns true or false whether the key exists or not respectively. |
map.size | Returns the number of items in the map |
map.clear() | Remove all items within the map |
Iterating a Map
Methods of Iteration | description |
---|---|
map.forEach((key,value,map) ⇒ {}) | Iterate over every key value pair within a map |
map.entries() | Returns a key/value pair iterator. This is the default iterator in Map.prototype[Symbol.iterator] |
map.keys() | Returns a key iterator |
map.values() | Returns a values iterator |
Concluding
In this chapter you learnt how you can take advantage of the new Map
data structure to store data by an arbitrary key of your choice. Map
is JavaScript’s implementation of a HashTable
, or a Dictionary
in C#, where you can use any type as key and as value.
You also learnt about the basic operations you can perform with a Map
, how you can store, retrieve and remove data, check whether or not a key exists within the Map
and how to iterate it in different ways.
Exercises
Sets, For When There Can Only Be One
We live in a world that celebrates personality. Enjoy your uniqueness, wear it on your sleeve, wherever you go. People will love you for it. - Lenrolc Srich Be yourself
You Are One of a Kind
A Set
is a data structure used to represent a distinct collection of items where each item is unique and only appears once. This is such a common need that, if you have been working with JavaScript for a little while, chances are that you have needed to roll your own implementation at some point. Well, you’ll need to do that no more because ES6 comes with a native Set
implementation. Hurrah!!
Working With Sets
You can create a new set using the Set
constructor:
Or from an iterable collection like an array:
As you can appreciate from the example above, the array had a duplicated value of earth
that is removed when creating the Set
. That’s because a Set
will automatically remove any duplicated items and only store each specific item once.
You can easily add more items to a Set
using the add
method:
The add
method is chainable, so adding multiple new items is very convenient:
You can check whether an item exists within a Set
by using the has
method:
And you can remove items from a set using delete
:
Additionally, you can get the number of elements within a set using the size
property:
And remove all the items from a set using clear
:
If you take a minute to reflect about the Set
API and try to remember the Map
from the previous chapter you’ll realize that both APIs are exceptionally consistent with each other. Consistency is awesome, it will help you learn these APIs in a heartbeat and write less error-prone code.
Let’s see how we iterate over the elements of a Set
.
Iterating Sets
Just like Map
you can iterate over the elements of a Set
using the for/of
loop:
In this case, instead of key/value pairs you iterate over each item within a Set
. Notice how the elements are iterated in the same order as they were inserted. The default iterator for a Set
is the values
iterator. The next snippet of code is equivalent to the one above:
The Set
also has iterators for keys
and entries
just like the Map
although you probably won’t need to use them. The keys
iterator is equivalent to values
. The entries
iterator transforms each item into a key/value pair where both the key and the value are each item in the Set
. So if you use the entries
iterator you’ll just iterate over [value, value]
pairs.
In addition to using either of these iterators, you can take advantage of the Set.prototype.forEach
method to traverse the items in a Set
:
Using Array Methods With Sets
The conversion between Sets
to Arrays
and back is so straightforward that using all the great methods available in the Array.prototype
object is one little step away:
We saw many of these methods in the Array’s chapter but we will see many more in the functional programming tome where we discover its secret LINQ-like abilities.
How Do Sets Understand Equality?
So far you’ve seen that a Set
removes duplicated items whenever we try to add them to the Set
. But how does it know whether or not two items are equal?
Well… It uses strict equality comparison (which you may also known as ===
or !==
). This is important to understand because it poses a very big limitation to using Sets
in real world applications today. That’s because even though strict equality comparison works great with numbers and strings, it compares objects by reference, that is, two objects are only equal if they are the same object.
Let’s illustrate this problematic situation with an example. Let’s say that we have a Set
of persons which, of course, are unique entities (we are all beautiful individual wonders just like precious stones):
We create a person object randalf
and we attempt to add it twice to the Set
:
The Set
has our back and only adds the person once. Since it is the same object, using strict equality works in this scenario. However, what would happen if we were to add an object that we considered to be equal in our problem domain?
So let’s say that in a new and innovative view of the world two persons are equal if they have the same properties, and particularly the same id
(Imagine randalf meeting randalf from the future, they are equal, but not the same):
Well, in that case, the object would be added to the Set
and as a result, and for all intents and purposes, we would have the same person twice. Unfortunately there’s no way to specify equality for the elements within a Set
as of today and we’ll have to wait to see this feature introduced into the language some time in the future.
We are free to imagine how it would look though, and something like this would work wonderfully:
In the meantime, if you need to use Set
-like functionality for objects your best bet is to use a dictionary indexing objects by a key that represents their uniqueness.
Sets Cheatsheet
Basic Operations
Basics | description |
---|---|
var set = new Set() | Create an empty set |
var set = new Set(iterator) | Create a set from an iterator |
set.add(‘value’) | Add an item to the set if it is not in the set already. The items added to the set can be of any type. It uses strict equality comparison to determine that. Chainable. |
set.delete(‘value’) | Remove item if it exists. Returns true if an item has been removed and false otherwise. |
set.has(‘value’) | Check whether an item exists in the set. Returns true or false whether the key exists or not respectively. |
set.size | Returns the number of items in the set |
set.clear() | Remove all items within the set |
Iterating a Set
Methods of Iteration | description |
---|---|
set.forEach((value,value,map) ⇒ {}) | Iterate over every item within a set |
set.value() | Returns a value iterator. This is the Set default iterator |
set.keys() | Returns a key iterator which just lets you iterate over the items within a set (just like values) |
set.entries() | Returns a key/value pair iterator which lets you iterate over pairs of value/value for those items within a set |
Concluding
The Set
is a new data structure in ES6 that lets you easily remove duplicates from a collection of items. It offers a very simple API very consistent with the Map
API and it’s going to be a great addition to your arsenal and save you the need to roll your own.
Unfortunately, at present, it has a big limitation that is that it only supports strict equality comparison to determine whether two items are equal. Hopefully in the near future we will be able to define our own custom version of equality and that day Sets will achieve their true potential. Until then use Set
with numbers and strings, and rely on Map
when you are working with objects.
Exercises
Book I. Epilogue
As they say, all good things must come to an end. I really hope you have enjoyed reading this book, that you’ve learned a lot of new stuff and that you’re super excited about writing some JavaScript!
Have an awesome day ahead of you!
– Jaime, your most humble servant
P.S. I added a bonus chapter! A preview that introduces you to the world of object oriented programming in JavaScript. Take a look. I think you’ll love it.
Tome I.III JavaScriptmancy and OOP: The Path of The Summoner (preview)
The Path of Summoning and Commanding Objects (Also Known as Object Oriented Programming)
Introduction to the Path of Summoning and Commanding Objects (a.k.a. Object Oriented Programming)
A Soft Introduction to OOP in JavaScript
Welcome to the Path of Summoning 1 and Commanding Objects! In this part of these ancient manuscript you’ll learn how you can work with objects in JavaScript, how to define them, create them and even how to interweave them. By the end of this part you’ll have mastered Object Oriented Programming in JavaScript and you’ll be ready to command your vast armies of objects into victory.
JavaScript OOP story is pretty special. When I started working seriously with JavaScript some years ago, one of my first concerns as a C# developer coming to JavaScript was to find out how to write a class. I had a lot of prowess in C# and I wanted to bring all that knowledge and ability into the world of JavaScript, so my first approach was to try to map every C# concept into JavaScript. I saw classes, which are such a core construct in C# and which were such an important part of my programming style at the time, as my secret passage to being proficient in JavaScript.
Well, it took me a long while to understand how to mimic classical inheritance in JavaScript but it was time well spent because along the way I learnt a lot about JavaScript and about the many different ways in which it supports object-oriented programming. This quest helped me look beyond classical inheritance into other OOP styles more adequate to JavaScript where flexibility and expressiveness reign supreme over the strict and fixed taxonomies of classes.
In this part of the book I will attempt to bring you with me through the same journey that I experienced. We will start with how to achieve classical inheritance in JavaScript, so you can get a basic level of proficiency by translating your C# skills into JavaScript and then we will move beyond that into new patterns that truly leverage JavaScript as a language and which will blow your mind.
Let’s get a taste of what is in store for you by getting a high level overview 2 of object-oriented programming in JavaScript. If you feel like you can’t follow the examples don’t worry. For in the upcoming chapters we will dive deeper in each of the concepts and constructs used, and we will discuss them separately and at a much slower pace.
C# Classes in JavaScript
A C# class is more or less equivalent to a JavaScript constructor function and prototype pair:
The constructor function represents how an object should be constructed (created) while the prototype represents a piece of reusable behavior. In practice, the constructor function usually defines the data members within a “class” while the prototype defines its methods.
You can instantiate a new Minion
object by using the new
operator on the constructor function:
As a result of instantiating an orc
we get a new Minion
object with two properties hp
and name
. The Minion
object also has a hidden property called [[prototype]]
that points to its prototype
which is an object that has a method toString
. This prototype and its toString
method are shared across all instances of the Minion
class.
When you call orc.toString
the JavaScript runtime checks whether or not the orc
object has a toString
method and if it can’t find it, like in this case, it goes down the prototype chain until it does. The prototype chain is established by the object itself, its prototype, its prototype’s prototype and so on. In this case, the prototype chain leads to the Minion.prototype
object that has a toString
method that would be called and evaluated as this.name
(orc
).
We can mimic classical inheritance by defining a new “class” Wizard
and make it inherit from Minion
:
We achieve classical inheritance by:
- calling the
Minion
constructor function from theWizard
constructor - assigning a
Minion
object (created viaObject.create
) as prototype of theWizard
“class”
With the constructor delegation we ensure that a Wizard
object has all the properties of a Minion
object. While with the prototype chain we ensure that all the methods in the Minion
prototype are available to a Wizard
object.
We can also augment the Wizard
prototype with new methods:
Or even override or extend existing methods within its base “class” Minion
:
Finally we can verify that everything works as expected by instantiating our very own powerful wizard:
As you can see from these previous examples writing “classes” prior to ES6 was no easy feat, it required a lot of moving components and a lot of code. That’s why ES6 brings classes along which provide a much nicer syntax to what you’ve seen thus far. This means that instead of having to handle constructor functions and prototypes yourself, you get the new class
keyword that nicely wraps both into a more coherent syntax:
And the extend
and super
keywords:
Where extend
lets you establish class inheritance and super
lets you access methods from parent classes. Again, we can verify that it works just like it did before by instantiating a classy wizard:
It is important to highlight though that ES6 classes are just syntactic sugar. Under the hood, these ES6 classes that you have just seen are translated into constructor function/prototype pairs.
And that is how you mimic classical inheritance in JavaScript. But let’s look beyond it.
OOP Beyond Classes
There are a lot of people in the JavaScript community that claim that the cause of JavaScript not having a nice way to mimic classical inheritance, not having classes, is that you were not meant to use it in the first place. You were meant to embrace prototypical inheritance which is the natural way of working with inheritance in JavaScript, instead of hacking it to make it behave sort of like classical inheritance.
In the world of prototypical inheritance you only have objects, and particularly objects that are based upon other objects which we call prototypes. Prototypes lend behaviors to other objects by means of delegation (via the prototype chain) or by the so called concatenative inheritance which consists in copying behaviors.
Let’s illustrate the usefulness of this type of inheritance with an example. Imagine that, in addition to wizards, we also need to have some thieves for when we need to use more gentle/shrew hand against our enemies. A ClassyThief
class could look something like this:
And let’s say that a couple of weeks from now, we realize that it would be nice to have yet another type of minion, one that can both cast spells and steals, and why not? Play some music. Something like a Bard. In pseudo-code we would describe it as follows:
Well we are in a pickle here. Classical inheritance tends to build rigid taxonomies of types where something is a Wizard
, something is a Thief
but it cannot be both. How would we solve the issue of the Bard
using classical inheritance in C#? Well…
- We could move both
castsSpell
andsteals
methods to a base classSpellCastingAndStealingMinion
that all three types could inherit. TheClassyThief
would throw an exception when casting spell and so would theClassyWizard
when stealing. Not a very good solution (goodbye Liskov principle 3) - We could create a
SpellCastingAndStealingMinion
that duplicates the functionality inClassyThief
andClassyWizard
and make theBard
inherit from it. This solution would imply code duplication and thus additional maintenance. - We could define interfaces for these behaviors
ICanSteal
,ICanCastSpells
and make each class implement these interfaces. Nicer but we would need to provide an specific implementation in each separate class. No so much code reuse here.
So none of these solutions are very attractive, they involve bad design, code duplication or both. Can JavaScript helps us to achieve a better solution to this problem? Yes it can
Imagine that we broke down all behaviors and encapsulated them inside separate objects (canCastSpells
, canSteal
and canPlayMusic
):
Now that we have encapsulated each behavior in a separate object we can compose them together to provide the necessary functionality to a wizard
, a thief
and a bard
:
And in a very expressive way we can see how a wizard
is someone than can cast spells, a thief
is someone that can steal and a bard
someone that not only can cast spells and steal but can also play music. By stepping out of the rigid limits of classical inheritance and strong typing we get to a place where we can easily reuse behaviors and compose new objects in a very flexible and extensible manner.
We can verify that indeed this approach works beautifully:
The Object.assign
in the examples is an ES6 method that lets you extend an object with other objects. This is effectively the concatenative prototypical inheritance we mentioned previously.
This object composition technique constitutes a very interesting and flexible approach to object-oriented programming that isn’t available in C#. But in JavaScript we can use it even with ES6 classes!
Combining Classes with Object Composition
Remember that ES6 classes are just syntactic sugar over the existing prototypical inheritance model. They may look like classical inheritance but they are not. This means that the following mix of ES6 classes and object composition would work:
In this example we extend the ClassyBard
prototype with new functionality that will be shared by all future instances of ClassyBard
. If we instantiate a new bard we can verify that it can steal, cast spells and play music.
This is an example of delegation-based prototypical inheritance in which methods such as steals
, castsSpell
and playsMusic
are delegated to a single prototype object (instead of being appended to each object).
So far you’ve seen classical inheritance mimicked in JavaScript, ES6 classes and object composition via mixin objects, but there’s much more to learn and in greater detail! Take a sneak peak at what you’ll learn in each of the upcoming chapters:
The Path of the Object Summoner Step by Step
In Summoning Fundamentals: an Introduction to Object Oriented Programming in JavaScript you’ll start by understanding the basic constructs needed to define and instantiate objects in JavaScript where constructor functions and the new
operator will join what you’ve discovered thus far about object initializers. You’ll review how to achieve information hiding and you’ll learn the basics of JavaScript prototypical inheritance model and how you can use it to reuse code/behaviors and improve your memory footprint. You’ll complete the foundations of JavaScript OOP by understanding how JavaScript achieves polymorphism.
In White Tower Summoning or Emulating Classical Inheritance in JavaScript you’ll use constructor functions in conjunction with prototypes to create the equivalent of C# classes in JavaScript. You’ll then push the boundaries of JavaScript inheritance model further and emulate C# classical inheritance building inheritance chains with method extension and overriding just like in C#.
In White Tower Summoning Enhanced: the Marvels of ES6 Classes you’ll learn about the new ES6 Class syntax and how it provides a much better class development experience over what it was possible prior to ES6.
In Black Tower Summoning: Objects Interweaving Objects with Mixins we’ll go beyond classical inheritance into the arcane realm of object composition with mixins. You’ll learn about the extreme extensibility of object-oriented programming based on object composition and how you can define small pieces of reusable behavior and properties and combine them together to create powerful objects (effectively achieving multiple inheritance).
In **Black Tower Summoning: Safer Object Composition with Traits ** you’ll learn about an object composition alternative to mixins called traits. Traits are as reusable and composable as mixins but are even more flexible and safe as they let you define required properties and resolve conflicts.
In *Black Tower Summoning Enhanced: Next Level Object Composition With Stamps ** you’ll find out about a new way to work with objects in JavaScript called *Stamps that brings object composability to the next level.
Finally, you’ll dive into the depths of Object Internals and discover the mysteries of the low level JavaScript Object
APIs and the new ES6 Reflection
APIs.
Concluding
JavaScript is a very versatile language that supports a lot of programming paradigms and different styles of Object-Oriented Programming. In the next chapters you’ll see how you can combine a small number of primitive constructs and techniques to achieve a variety of OOP styles.
JavaScript, like in any other part of the language, gives you a lot of freedom when working with objects, and sometimes you’ll feel like there are so many options and things you can do that you won’t know what’s the right path. Because of that, I’ll try to provide you with as much guidance as I can and highlight the strengths and weaknesses of each of the options available.
Get ready to learn some JavaScript OOP!
References and Appendix
Appendix A. Setting Up Your Developing Environment For ES6
The best way to get started with ES6 is by using an interactive online REPL. Here is a list of some of my favorites:
- Babel REPL - bit.ly/babel-repl. Babel is a ES6 transpiler that let’s you take advantage of ES6 and ESnext features today. It is the de facto ES6 transpiler.
- jsBin - jsbin.com. JsBin is a very popular web prototyping tool with a customizable set of pans to visualize HTML, CSS, JavaScript, a console and the output.
- jsFiddle - jsfiddle.net. JsFiddle is yet another popular prototyping tool that let’s you look at your HTML, CSS, JavaScript and output at a glance.
- CodePen - codepen.io is a web prototyping tool and community.
- ES6 Katas - es6katas.org is a collection of interactive katas to learn ES6.
Using ES6 with Node.js
In addition to using prototyping tools for the web, node.js has great support for ES6 as you can appreciate in these compatibility table. But it you want to be able to use all features of ES6 and ESnext you can take advatange of babel.js and the babel-node
REPL.
You can install it using the following command:
And start it using babel node
:
This will open a REPL that has complete support for ES6.
ES6 and Modern Browsers
Modern browsers also have an increasing support for ES6. The ES6 compability table can give you a general idea as to how the efforts from the different vendors are going.
The problem with developing for the browser is that you cannot control the runtime in which your application is running like you do when developing a backend in node.js. This means that you cannot rely on your user’s browser having the features that you need or want to use. Because of that, transpiling your application from ES6 to ES5 becomes crucial in these environments to make sure that it works in a myriad of devices and can reach as many users as possible.
There’s a wide variety of tools that let you transpile your ES6 code to something that can work on any browser and setup a real world ES6 development environment.
Real-World ES6 Development Environments
The de facto standard for transpiling ES6 is babel.js. It is very extensible and can be plugged into any of the modern front-end build pipelines. It uses a plugin system that lets you easily decide which features of ES6 and ESnext you want to enable.
Depending on your build tooling of choice you’ll need to follow different steps to start using Babel. You can find numerous and extensive guides for Gulp, WebPack, Grunt, Broccoli, etc at bit.ly/setup-es6.
Appendix B. Fantasy Glossary
If you are not familiar with the genre of fantasy you may have a hard time understanding some of the words I use in this book. Hopefully this glossary will give you some guidance in this respect.
- Arcane: Something that is mysterious or secret. Known or understood by very few people.
- Alchemy: A science that was used in the Middle Ages with the goal of changing ordinary metals into gold. Also a power or process that changes or transforms something in a mysterious or impressive way.
- Cimmerian barbarian: Barbarian from the extreme confines of Cimmeria.
- Conan: “Hither came Conan, the Cimmerian, black-haired, sullen-eyed, sword in hand, a thief, a reaver, a slayer, with gigantic melancholies and gigantic mirth, to tread the jeweled thrones of the Earth under his sandalled feet.”
- Balefire: Balefire is a weapon of the One Power. When a target is struck with balefire, its thread in the Pattern is destroyed, in an amount proportional to the power of the balefire strike. This translates to both the target’s existence, and actions up to a certain point, being retroactively erased.
- Gandalf: Mighty wizard that has the magic ability to always be on time.
- Goblin: An ugly and sometimes evil creature that likes to cause trouble.
- Golem: An artificial creature being endowed with life by magic. It is often associated to different elements and materials: fire, earth, sand, etc.
- Hobbit: Hobbits are similar to humans, but about half their size. They’re chubby, furry-footed home-bodies with a penchant for dwelling in hollowed out hillsides and a racial talent for burglary.
- Halfling: see Hobbit.
- JavaScript-mancer: Person that has mastered the art of writing awesome JavaScript and has an intimate knowledge of it.
- JavaScript-mancy: The arcane art of using JavaScript to alter the world around you.
- Kender: A race of wizened 14-year-olds that, unlike halflings, wear shoes.
- Mana: For those of you not familiar with magic, mana can be seen as a measure of magical stamina. As such, doing magic (like summoning minions) spends one’s mana. An empty reservoir of mana means no spellcasting just as a empty reserve of stamina means no more running.
- Minion: Someone who is not powerful or important and who obeys the orders of a powerful leader or boss.
- Saruman: Powerful wizard prone who likes white clothing and prone to evil deeds
- Scepter: A staff or baton borne by a sovereign as an emblem of authority. It can be imbued in magic powers.
- Spell: A spoken word or form of words held to have magic power.
- Spellcasting (casting): Performing magic by reciting a spell.
- Summon: To bid a creature to come to your aid with the help of magic. It can also create a creature from nothingness.
- Troll: An evil giant creature than inhabitates caves, hills and bridges. Some of them show weakness to sunlight.
- Teleport: Transfer ones location by using magic
- Orc: A race of human-like creatures, characterized as ugly, warlike, and malevolent.
- Orb: A circular object that possess unbound magic power.
- Wand: A long, thin stick used by a magician to channel its powers.
- Weave: See spellcasting.
References
There’s a lot of books that have inspired me while writing JavaScript-mancy. Here is a non exhaustive list of the most influential.
Specifications
Books
- JavaScript Allonge - Reginald Braithwaite
- You don’t know JS - Kyle Simpson
- Functional JavaScript - Michael Fogus
- Effective JavaScript - David Herman
- Understanding ECMAScript 6 - Nicholas C. Zackas
- Secrets of the JavaScript Ninja - John Resig, Bear Bibeault
- Programming JavaScript Applications - Eric Elliott
- Principles of Object Oriented JavaScript - Nicholas C. Zackas
- Eloquent JavaScript - Adam Freeman
- JavaScript the Good Parts - Douglas Crockford
Notes
1“Any sufficiently advanced technology is indistinguishable from magic.” Arthur C. Clarke. Love that quote :)↩
2The ECMAScript standard in which JavaScript is based is evolved by the TC39 (Technical Committee 39) composed of several companies with strong interest in JavaScript (all major browser vendors) and distinguished members of the community. You can take a look at their GitHub page for a sneak-peek into how they work and what they are working in↩
Tome I. Mastering the Arcane Art of JavaScript-mancy
1For those of you that are not fantasy nerds I have included a small glossary at the end of the book where you can check words that you find strange. You should be able to understand the book and examples without the glossary, but I think it’ll be more fun if you do↩
2This is a gross oversimplification. If you’ve read some traditional literature about static vs dynamic programming languages you’ll be familiar with the idea that static programming languages like C++, Java, C# are compiled and then executed whereas dynamic programming languages like Ruby, Python or JavaScript are not compiled but interpreted on-the-fly as they are executed. The repercussions of this being that a compiled program cannot be changed at runtime (you would need to recompile it), whereas an interpreted one can, since nothing is set in stone until it is run. In today’s world however, JavaScript runtimes like V8 (Chrome) or SpiderMonkey (Mozilla) compile JavaScript to machine code, optimize it, and re-optimize it based on heuristics on how the code is executed.↩
3For those of you not familiar with magic, mana can be seen as a measure of magical stamina. As such, doing magic (like summoning minions) spends one’s mana. An empty reservoir of mana means no spellcasting just as a empty reserve of stamina means no more running.↩
4As an article of interest you can augment objects in C# if you use the dynamic
keyword with ExpandoObject
s↩
5One does not simply change the prototype of an object willy-nilly at runtime since it can affect performance a lot. Instead, you would use Object.create or a function constructor, and if needed, you would augment the prototype as needed.↩
6like a hobbit but with shoes. If curious look up the joyful, corageous and beloved Tasslehoff Burrfoot.↩
7in reality, it does not need to be an array, but an iterable that produces key/value pairs [<key>:<value>]
↩
8for the sake of correctness, you can use the for/of loop not only on arrays, maps and sets but on anything that implements the iterable protocol. We will discuss iterability later within the series.↩
9An interesting thing to think about is that Array.from
can be easily polyfilled while the rest syntax requires transpilation. If you, for some reason, cannot or don’t want to add the transpilation step to your project then you can still use Array.from
by adding a polyfill or a shim. Which is a very painless alternative.↩
10Open for extension and closed for modification. http://bit.ly/ocp-wikipedia↩
11As long as it is not frozen via Object.freeze
, which makes an object immutable to all effects and purposes.↩
12I say mostly because if you have a this
keyword within a method and within a callback function (which I dare say is pretty common) then you are screwed. But worry not! You’ll learn everything there is to learn about this
in the next chapter.↩
13or the new operator that we’ll see when we get to glorious tome of OOP ↩
14that’s from the one and only JavaScript specification ECMA-262 (http://bit.ly/es6-spec-symbols)↩
15AJAX stands for Asynchronously JavaScript and XML
and is a technology that allows you to get data from a server even after a web page has already been loaded. The significance and impact of AJAX in modern web development is huge because not only does it let you create highly interactive websites but also deliver a website in chunks as they are needed. Since its inception, browsers have implemented support for AJAX via the XMLHttpRequest object. Because of its complexity, I decided to use the simpler $.getJSON
. In the near future, you’ll be able to do AJAX requests using the improved fetch
API. Yey!↩
16You can find more information about the Window object and the DOM at MDN (http://bit.ly/mdn-window-object)↩
17Another cool use of bind
is partial application, but we’ll take a look at that when we get to the tome of functional programming.↩
18In this particular case however, because we are using jQuery to perform an AJAX request, the value of this
is jQuery jqXHR
object, an object that represents the AJAX request itself (we can assume that jQuery calls the updateUsers
callback in the context of a jqXHR
object).↩
19Check this awesome jsJabber chapter to learn more about the origins of JavaScript from the very illustrious Brendan Eich http://bit.ly/js-origin.↩
20Template literals are also known as String Templates↩
21The next step would be to create two methods first
and last
that would encapsulate these two implementation and extend the Array.prototype
object. Soon we will take a look at that within the OOP section of the book.↩
22Find out more about arrow functions within the spec at http://bit.ly/es6-spec↩
23The DOM or Document Object Model is an object representation of a website where each HTML element is represented by an object called a node.↩
Tome I.II JavaScriptmancy and Data Structures
1The for/in loop let’s you iterate over all the enumerable properties of an object. Later in this section of the book you’ll learn more about the concept of enumerability and how it differs to the concept of iterability introduced in ES6.↩
2See bit.ly/javascriptmancy-is-this-an-array for more info on why instanceof is not a safe way to determine that an object is an array.↩
Tome I.III JavaScriptmancy and OOP: The Path of The Summoner (preview)
1In Fantasy, Wizards of all sorts and kinds summon or call forth creatures to act as servants or warriors and follow the wizard commands. As a JavaScript-mancer you’ll be able to use Object Oriented Programming to summon your own objects into reality and do with them as you please.↩
2In this section I am going to make a lot of generalizations and simplifications in order to give a simple and clear introduction to OOP in JavaScript. I’ll dive into each concept in greater detail and with an appropriate level of correctness in the rest of the chapters about OOP.↩
3The Liskov substitution principle is one of the S.O.L.I.D. principles of object-oriented design. It states that derived classes must be substitutable for their base classes. This means that a derived class should behave as portrayed by its base class and not break the expectations created by its interface. In this particular example if you have a castsSpell
and a steals
method in the base class, and a derived class throws an exception when you call the steals
method you are violating this principle because the derived class breaks the expectations established by the base class (i.e. that you should be able to use both methods).↩