The Minimum Javascript You Should Know
The Minimum Javascript You Should Know
of Contents
Introduction 1.1
0. Data Types 1.2
1. Scopes 1.3
2. Functions 1.4
3. Inheritance 1.5
4. Immutability 1.6
5. Async 1.7
6. Module 1.8
7. Language Quirks & Features 1.9
8. Epilogue 1.10
The Minimum JavaScript You
Should Know When You Code
React & Redux
That aside, if you pick this book, chances are your team is migrating to React/
Redux or your architecture team has decided that the React/ Redux is the
“strategic” UI framework to adopt for the enterprise.
You searched on Google for “react redux tutorial” and you found lots of
JavaScript syntaxes alien (probably because you’re from a Java/ C#
background and the last time you coded JavaScript was a tiny validation
script using JQuery in 2008). But that’s no biggie! You embrace the virtue of
continuous learning. You brag about: “I’m a polyglot developer yo!”. And
then, you decided to get several books on JavaScript: probably Eloquent
JavaScript, JavaScript Allonge or even Understanding ES6. But Argh! they
are all too verbose. Most of all, you are not a programming noob! You know
what variables and conditional constructs are. You simply don’t have time to
waste on these basics. Well, I’ve been there too buddy. And that’s why I wrote
this pocket book (aka cheatsheet) to prep people like you transition quickly
from basic JavaScript & intermediate programming knowledge to being able
to productively follow through React/ Redux tutorials on the web.
Godspeed!
Prerequisites
Since this book will only cover subtleties & nuances of JavaScript, you
should at least have the below prerequisites to follow along:
Let’s see what happens if you mix 2 different types (e.g. String and
Number ):
Hmm.. It’s quite intuitive. + acts as a concat method and as the first argument
is String , JavaScript will convert the second one as String as well. What
if we reverse it, though (i.e. Number + String ):
Whoa! It’s still the same! We can still rationalize and say that String is
somehow stronger than Number . Also, you might come from Java
background and say that this is also in line with the behavior in Java. Just
when you think you get the hang of it:
Whoa Whoa Whoa! What’s happening here? Rather than trying to explain the
actual complicated and baffling rules deriving the above results, I’ll just leave
2
you with a quote and a meme :
“Oh! It’s just JavaScript being JavaScript.”.
1. Don’t mix your types. It sometimes behaves intuitively, but other times,
it doesn’t. You don’t want to end up spending countless hours debugging
the latter scenario.
2. When there’s no compiler to help you with types. Unit test is your best
friend.
3. Don’t rely on JavaScript’s automatic type conversion. You don’t want to
memorize all its rules and certainly should not expect the reader of your
code to know of all of them by heart.
Type Coercion Comparison
There are 2 types of equality comparators in JavaScript: == (double equals)
and === (triple equals).
The former will use automatic type conversion (type coercion) if the 2
operands are not of the same type:
The lack of commutative & transitive properties will produce hard to trace
bugs.
Truthy & Falsy value
Unlike in strongly typed languages, any values in JavaScript can be used as a
boolean check. When JavaScript expect a boolean type but given a non-
boolean type, JavaScript will convert it to its corresponding boolean value. A
non-boolean value which converts to true is called truthy; otherwise, if it
converts to false , it’s called falsy.
The below are some of the truthy or falsy values worth remembering:
The behavior above gives rise to one of its most popular idioms: short circuit
operator. Basically, instead of doing null or undefined check in an if
guard, you can just use && :
function funcWhichMightReturnNull(shouldReturnNull) {
if (shouldReturnNull) {
return null;
} else {
return {
toPrint: 'print me'
};
}
}
const test = funcWhichMightReturnNull(false);
// instead of verbose:
if (test) {
console.log(test.toPrint);
}
// you can do:
console.log(test && test.toPrint); //=> print me
const test2 = funcWhichMightReturnNull(true);
// instead of verbose:
if (test2) {
console.log(test2.toPrint);
}
// you can do:
console.log(test2 && test2.toPrint); //=> null
// (But No error/ exception)
function Mailbox(props) {
const unreadMessages = props.unreadMessages;
return (
<div>
<h1>Hello!</h1>
{unreadMessages.length > 0 &&
<h2>
You have {unreadMessages.length} unread messages.
</h2>
}
</div>
);
}
Defaulting
The || boolean conjunction behaves the opposite of && . So, if the left
operand is falsy, it will evaluate and return the right operand. If the left
operand is truthy, it will just return it.
Similar to short circuit check, you will see this common idiom in JavaScript
to provide default values:
function funcWhichMightReturnNull2(shouldReturnNull) {
if (shouldReturnNull) {
return null;
} else {
return 'Result';
}
}
// instead of verbose:
if (test3) {
console.log(test3); //=> Result
} else {
console.log('function returns null');
}
// instead of verbose:
if (test4) {
console.log(test4);
} else {
console.log('function returns null'); //=> function returns
null
}
Again, this defaulting is common in React. For instance, when setting default
value for properties:
return (
<button onClick={props.onClick}>{props.message || "Default
text"}</button>
);
memes ↩
1. Scopes
Importance of var
JavaScript has a var keyword which declares a variable within a function
scope.
JavaScript is quite lenient, though. If you forget the var prefix, JavaScript
will just attach your variable to the global scope. But as seen below, it’s a
poor choice of default behavior:
console.log(bonusMultiplier); //=> {
// developer: 1.1,
// manager: 2,
// executive: 3.8
// }
We can use strict mode to prevent this runtime issue, though. Instead of
attaching the variable to global scope, JavaScript in strict mode will default
non-var-prefixed variables to be undefined. We tell the JS compiler to use
strict mode by adding 'use strict'; expression at the top of our JS file:
'use strict';
In conclusion, if you forget to use var to declare your function scope, not
only are you polluting/ cluttering the global namespace, you might also leak
out confidential information. Using strict mode can prevent you from doing
this. So, always use strict mode!
Hoisting
Declarations of var s are said to be “hoisted” in JavaScript. What it means is
simple, when you do:
function hoistMe() {
dosth();
var a = 20;
dosth();
}
what the JavaScript compiler will do is actually to bring up the var declaration
to the top of the function:
function hoistMe() {
var a; // Look Ma! declaration moved to the top!
dosth();
a = 20;
doSth();
}
Notice that only the declaration is hoisted, not the assignment. This brings to
a commonly followed style to always declare var s at the top of your
function; because most JavaScript newbies are not aware of this feature.
In addition, you should know that function declarations are also hoisted.
That’s why I can invoke a function even before declaring it:
// invoke function
dosth(); //=> doing something
// declared below
function dosth() {
console.log("doing something");
}
Style Purists (aka Nazis) such as Doug Crockford argue that function
expressions are the better way as relying on hoisting is seen as showing lack
of discipline (aka sloppiness).
Exercise:
What would be printed in the below code?
printMe();
function printMe() {
var a = 0;
console.log(a);
console.log(b);
var b = 1;
console.log(b);
console.log(c);
}
Answer:
0
undefined
1
ReferenceError: c is not defined
Block Scope
I haven’t fully emphasized the fact that var is function scoped:
function test() {
var i; // var is hoisted to the top of the function
for (i = 0; i<10; i++) {
console.log(i);
}
console.log('test: value of i: ' + i); // obviously i is
// still available here.
}
The difference between let and const is as the name implies. const is a
constant, and therefore, it doesn’t allow re-assignment of values:
Public Service Announcement (PSA): ditch var and always use let and
const ! Before ES2015, JavaScript doesn’t have any facility for block
scoping and people were doing gymnastics such as IIFE to confine variable
scopes. It’s now 2018. JavaScript have modules and block scope variables
which allows you to easily achieve encapsulation. Utilize them!
Nested Scope
Scopes are nested as how you would expect in other languages. That is, a
child scope has access to its parent scope and child scope can shadow (create
its own copy of its parent’s variables):
function doA() {
var a = 1;
function doB() {
var b = 2;
console.log(b);
console.log(a); // a is available from parent
}
doB();
console.log(b); // b was only in doB()
}
doA(); // => 2
// => 1
// ReferenceError: b is not defined
doC(); // => 4
// 33 (shadowing works!)
// 3 (parent's variable is untouched!)
I only showed examples of var because for let , nested scope behavior is
pretty much as intuitive as other languages (e.g. C# or Java).
2. Functions
function executeTwice(funcToExecute) {
funcToExecute();
funcToExecute();
}
executeTwice(function() {
console.log('execute me twice!');
});
//=> execute me twice!
//=> execute me twice!
Currying & Composition
Being able to pass functions around gives rise to patterns of functional
composition as a way to achieve re-use.
// non-curried add
function add(a,b) {
return a + b;
}
add(2,5);
// curried add:
function add(a,b) {
return function(a,b) {
return a +b; };
}
}
console.log(increment(5)); //=> 6
console.log(increment(99)); //=> 100
Exercise
Create a function called prepend, which can be invoked in curried-style. e.g.
Answer:
function prepend(prefix) {
return function(content) {
return prefix + content;
}
}
Arrow Functions
Since ES 2015, there is shorter way to declare anynomous functions:
// pre-ES2015
const traditional = [1, 2, 3].map(function (x) {
return x * 2;
});
// ES2015
const arrow = [1, 2, 3].map((x) = { return x * 2; });
console.log(arrow); //=> [2, 4, 6]
// Or... // we can omit curlys and return if it's just a one line
expression
Anonymous and arrow functions are not exactly equivalent, though. For now,
you can take it that they can be replaced one-to-one; nonetheless, we will
revisit arrow functions again when we look at the this keyword binding in
the later chapters.
Collection Style Programming
Collection-style or Box-style programming is a popular way to make use of
higher order functions.
// pre-ES2015
const result0 = [1, 2, 3]
.map(function(x) { return 2 * x;})
.filter(function(x) { return x > 2; })
.reduce(function(accu, curr) { return accu +
curr;}, 0)
console.log(result ); //=> 10
you get the hang of it, you’ll forget other ways of manipulating collection
without them!
Exercise:
You have an array of users
use collection-style programming to return the just the names of the female
users.
Answer:
// pre-ES2015
users
.filter(function(user) { return user.gender === 'F'; })
.map(function(user) { return user.name; });
// ES2015
users
.filter(u => u.gender === 'F')
.map(u => u.name);
// GOOD
const pendingTodos = todos.filter(todo => !todo.isDone);
No, people, closures are not the same as arrow functions. Closures are:
1. functions
2. who still have access to their parent’s scope (fancy term: lexical
environment)
3. even while their parent functions have already ended (exited)
function makeCounter() {
// counter variable lives in makeCounter's scope
let counter = 0;
return function() {
// this anonymous function has access to counter
return ++counter;
}
// 3. parent function (makeCounter) exits
}
console.log(firstCounter()); //=> 1
console.log(firstCounter()); //=> 2
// 2. since it keeps incrementing,
// it's clear that variable counter is still retained
For example, we actually had seen closure in action in our currying example:
function makeAdder(x) {
// x is a variable in the parent function scope
return function(y) {
// 2. x is accessible in this inner function
return x + y;
};
// 3. parent function exits
}
console.log(add5(2)); // 7
console.log(add10(2)); // 12
See! We’ve been using closures without even knowing it! Closure is actually
quite intuitive. In fact, without closure, reasoning about your code will be
very hard!
Lastly, it’s fine if you don’t fully grasp what closure is. Just please, for the
posterity’s sake, stop spreading false definitions!
3. Inheritance
Skippable Ramblings
You should have heard that JavaScript is a prototype-based language. Its
mechanism of inheritance is through the prototypes chain (instead of classes
hierarchy). Understanding how prototypical inheritance works in JS is
essential. Sadly, though, people from Java/ C# or other class-based languages
rarely invest their time to learn this paradigm. As a consequence, in ES2015,
JavaScript introduced classes; which is merely a syntactic sugar to help
people from the class-based inheritance camp to adopt JavaScript.
would decide to go for the pragmatic path. That is, let’s look at how classes
work in JavaScript
Classes
As seen above, syntax for defining a class is pretty similar to C#/ Java, except
we don’t need to worry about types and constructor uses the constructor
keyword instead of the class name. Instantiating a class is equally similar:
I know, I know, you must be thinking: who in the right mind has Honda Jazz
as his favorite car? Has he ever heard of Bugatti Veyron? Lamborghini
Veneno? or Ferrari F60? But that’s not important for now. What’s more
important is the fact that you can extend classes:
getDisplayName() {
return super.getDisplayName() + ' [Automatic Transmission]';
}
You extend a class by using the extends keyword and you can easily
override a super classes’ method by declaring another method with the same
signature. In case you need access to the super class’ method, the keyword
super is there to help.
Again, the syntax is eerily similar to Java, giving you the illusion that
JavaScript inheritance is the same as Java’s inheritance.
// the only car better than Honda Jazz is the Automatic version
of Honda Jazz
const autoHonda Jazz = new AutoCar ('Honda', 'Jazz');
console.log(autoHonda Jazz.getDisplayName()); //=> 'Honda Jazz
[Automatic Transmission]'
Equipped with this knowledge of classes, the following React snippet should
seem very familiar now (apart from the JSX which is out of scope of this
book):
Final Notes
There are many good tutorials out there about JavaScript Prototypical
inheritance. One I would recommend reading is the MDN’s official guide:
https://developer.mozilla.org/en-
US/docs/Learn/JavaScript/Objects/Inheritance.
For completeness sake, below is the example in this chapter written the
prototype way:
Car.prototype.getDisplayName = function () {
return `(${this.brand}) ${this.make}`;
}
AutoCar.prototype = Object.create(Car.prototype);
AutoCar.prototype.constructor = AutoCar;
AutoCar.prototype.getDisplayName = function() {
return Car.prototype.getDisplayName.call(this) + ' [Automatic
Transmission]';
}
It’s obviously more verbose; nonetheless, it’s very explicit that AutoCar
inherits directly from an Object ( Car ) through the virtue of the prototype
chain.
4. Immutability
Arrays
The above code is perfectly fine for most use cases. However, Redux state-
tree optimization relies on object reference check ( === ). This means that
modifying the existing array defeats the assumption that “if object reference is
same, the object is equal”. So, a more redux friendly approach is to use
array’s concat :
console.log(arr1);
//=> [1, 2, 3] (Original array is intact!)
console.log(arr2);
//=> [1,2,3,4]
Objects
// How do we add an attribute to an object?
var person = {name: "Tomy" };
// Simple, just use the brackets notation!
person['gender'] = 'M';
console.log (person);
//=> {name: "Tomy", gender: "M"}
// Better.. immutable
var originalPerson = {name: "Tomy" };
var personWithGender = Object.assign({}, originalPerson, {gender:
'M' });
console.log (originalPerson);
//=> {name: "Tomy"} (Original object is intact!)
console.log (personWithGender);
//=> {name: "Tomy", gender: "M"}
In short, the ... (spread) notation, lets you copy over the properties of the
old object:
console.log(iPhone7);
//=> {version: 7, model: "Iphone", ram: "3GB",
batteryLifeInHours: 10, price: 700}
// original object intact!
console.log(iPhone8);
//=> {version: 8, model: "Iphone", ram: "3GB",
batteryLifeInHours: 10, price: 700}
console.log(iPhone8InMarket);
//=> {version: 8, model: "Iphone", ram: "3GB",
batteryLifeInHours: 10, price: 1000}
The above is purely for fun. No harm or foul intended. In fact, to be honest,
I’m actually an Apple fanboy.
Conceptual Check!
Does using const guarantee immutability?
In conclusion, NO! Using const doesn’t mean that your data structure is
safe from being mutated. It just means that it can’t be reassigned to another
item. The item itself, though, can be easily altered. Don’t mix immutability
the const !
Apologies for those who don’t get the Star Wars reference, though.
Exercise
Use Object spread operator to fill in the Fill me branch below:
// state is defined as
const state = {
name: 'Bob',
gender: 'M'
}
// Expected result:
console.log(reducer(state, action)); //=>
{name:'Tomy',gender:'M'}
Answer:
Notes on performance
What if your object is large? Or your array contains millions of items?
Copying them over everytime you need some change seems like a terribly bad
performance idea right? That’s true. But fret not, there are libraries like Mori
and Immutable JS which can help you avoid this performance penalty by
employing advance techniques of Persistent Data Structure. So if you ever
find that your object or array grows too large and your profiling shows
copying them over and over is the bottleneck, do check out those libraries.
5. Async
Hard prerequisites:
Event loop is the concurrency model adopted by JavaScript. I will now
outsource the explanation of how the event loop works to the guy who does
this best, Philip Roberts: What the heck is the event loop anyway?
Do not, I repeat, do not continue reading without watching the above video!
Quiz:
To check your understanding of the event loop, let’s have a small quiz. What
would the below print out?
(function() {
console.log(1);
setTimeout(function() {console.log(2); }, 1000);
setTimeout(function() {console.log(3); }, 0);
console.log(4);
})();
Answer:
//=> 1
//=> 4
//=> 3
//=> 2 (1 second later)
If you still don’t understand why? I’d advice you to re-watch the event loop
video recommended above.
1. Callback
2. Promise
3. Async-Await
jQuery.ajax({
url: localSearchUrlPrefix + city,
success: function(result) {
console.log('woeid: ' + result[0]['woeid']);
jQuery.ajax({
url: locationUrlPrefix + result[0]['woeid'] + '/',
success: function (result) {
console.log('Result:', result.consolidated_weather);
console.log('Weather today:',
result.consolidated_weather[0].weather_state_name);
}
});
}
}); //=> woeid: 1062617
//=> Result: <...>
//=> Weather today: <...>
Promise is just like callback, except that you pass the callback function by
fetch(localSearchUrlPrefix + city)
.then((response) => response.json()) // you need to explicitly
// get the JSON body
.then((result) => {
console.log('woeid: ' + result[0]['woeid']);
// returning Promise inside a Promise below
return fetch(locationUrlPrefix + result[0]['woeid'] + '/');
})
.then((response) => response.json()) // indeed having to do
this
// is quite annoying..
.then((result) => {
console.log('Result:', result.consolidated_weather);
console.log('Weather today:',
result.consolidated_weather[0].weather_state_name);
});
//=> woeid: 1062617
//=> Result: <...>
//=> Weather today: <...>
function resolveAfter1Second(x) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(x):
}, 1000);
});
}
function addTraditional() {
return resolveAfter1Second(20)
.then((a) => resolveAfter1Second(30)
.then((b) => a + b)
);
}
addTraditional().then(console.log);
//=> 50 (2 seconds later)
There is no doubt the above code reads clearer. Async await is indeed the way
of the future. Nevertheless, its underlying mechanism still relies on Promises
(and Generators). Moreover, plenty of React articles out there still use
Promises. Thus, knowing how Promise works is still essential.
One last note: the above example still resolves after 2 seconds. What if I want
it to execute in parallel and end in 1 second? Well, for that, we need the help
of our good friend, Promise.all :
addAsyncAwaitParallel().then(console.log);
//=> 50 (1 second later)
Exercise:
Rewrite the Promise-based weather example in Async/ Await style.
Answer:
Before I start the discussion about modules, I have the confession to make. I,
myself, still get confused by it. Unlike in Java/ C# (where you can just auto-
import stuffs), working with JavaScript’s module is still mostly manual (I
don’t recall Visual Studio Code has the feature to optimize imports yet).
Moreover, module has been a hot debate topic causing its proposals and
implementations to have been revised numerously. So, to avoid confusion,
let’s start with a history lesson, shall we?
IIFE (Immediately Invoked Function
Expression)
In the olden days, there is no way to encapsulate pieces of JavaScript code
together in a module. Ben Alman noticed that functions can be used to
encapsulate scope and proposed that very way to simulate ‘module pattern’.
IIFE is short for Immediately Invoked Function Expression. As the name
imply, it’s a function expression (i.e. (function() { ... }) ) and it’s
immediately invoked (i.e. () suffix) . Let’s see the example below:
(function() {
var a = "1";
var b = "2";
console.log(a + b);
})();
//=> 3
Since IIFE was the only way to hide variable access in the past, the world of
JavaScript is rampant with the above idioms. Another pattern is to leverage on
closure to create module which can expose selective functions/ attributes,
appropriately named as the Revealing Module Pattern:
return {
add: function() {
sum = sum + 1;
return sum;
},
reset: function() {
return sum = 0;
}
}
})();
console.log(counter.add()); //=> 1
counter.reset(); //=> 0
CommonJS
Node.js came along and as any other server-side solution, support for
modularity is a must. Node’s module implementation is based on CommonJS
specification. In a nutshell, CommonJS has:
So, for example, we can define the below module in a file called mod1.js :
// define 2 functions
const myFunc1 = function(){ console.log('myFunc1');};
const myFunc2 = function(){ console.log('myFunc2');};
Now that these functions are exposed, we can use them in mod2.js as long
as we declare our dependencies:
We can also export classes as classes are just syntatic sugar for functions
anyway:
class Person {
constructor(name) {
this.name = name;
}
sayHello() {
// search about JavaScript Template Literals
// if you're amazed with the below syntax.
console.log(`Hello! I am ${this.name}. `);
}
}
module.exports = Person;
Many React examples will use this way to declaring module dependencies
and now you know how to decipher those examples :)
AMD (Asynchronous Module
Definition)
Folks on the browser-side were not satisfied with CommonJS, though.
Specifically, they complained about the lack of asynchronous loading support
in the browser environment. That’s why they decided to fork commonJS and
created a new module API called Asynchronous Module Definition (AMD).
One implementation of AMD is RequireJS. You will rarely encounter React
examples using RequireJS, though. It is simply because by the time React
came about, module bundler such as Webpack rose to fame and Webpack
doesn’t favor this RequireJS syntax. Nevertheless, for completeness sake, I’ll
show a snippet for AMD:
1. module name
2. array of module dependencies
3. function defining the module body.
The ES6/ ES2015 Module
ES6 module relies on 2 keywords: import & export . Let’s look at the
simplest example, default export/ import.
Notice that since it’s a default export, the “imported name” doesn’t really
matter. As seen below, you can assign the imported function as any other
name:
// exporting
export default 7*5;
The user of this constants can import them (notice the curly braces!):
Finally, if you want to import all exported items from a module, you can use
* wildcard import:
// Named export
export class Component {
// ...
}
// Default export
export default {
Component,
PureComponent,
createElement,
// ...
}
Exercise
Convert the below CommonJS-based modules to ES2015:
module.exports = {
add: add,
multiply: multiply
}
Answer:
Since it’s a multiple export, default exports will not cut it.
I chose to use wildcard import below, but a selective named imports will also
do:
console.log(lib.add(10,20)); //=> 30
console.log(lib.multiply(10,20)); //=> 200
7. Language Quirks & Features
this
function sayName() {
console.log('Hello I am ' + this.name);
}
const ben = {
name: 'Ben',
sayName: sayName
};
const bob = {
name: 'Bob',
friend: ben,
sayName: sayName
};
class Car {
constructor (brand, make) {
this.brand = brand;
this.make = make;
}
getDisplayName() {
return `(${this.brand}) ${this.make}` ;
}
}
function greet(isLoud) {
if (isLoud) {
console.log('YOYOYOYO! I am ' + this.name + '!!!');
} else {
console.log('Hi, I am ' + this.name);
}
}
console.log('// bind');
const benGreeting = greet.bind(ben);
benGreeting(true); //=> YOYOYOYO! I am Ben!!!
Quiz
Let’s test our understanding with an example:
var batman = {
_name: 'Bruce Wayne',
getSecretIdentity: function() {
return this._name;
}
}
Answer
function useThis() {
console.log(this);
}
Arrow functions are exempt from this rule, though. Since arrow function was
initially designed to be lightweight, it’s just right that it doesn’t need their
own lexical scope (i.e. can borrow from its parents).
const mark = {
name: 'Mark',
friends: [{name: 'Eduardo'}, {name: 'Dustin'}],
listFriends: function() {
this.friends.forEach(function(friend) {
// ----- FIX ME -----
// If I uncomment the below,
// the compiler will say that this is undefined:
//
// this.greetFriend (friend.name); });
});
},
greetFriend: function(name) {
console.log('Hi ' + name + "!");
}
}
// 3. use bind
listFriends: function() {
const greetFriend = this.greetFriend.bind(this);
this.friends.forEach(function(friend) {
greetFriend(friend.name);
});
}
Quiz
What will be printed below?
var myObject = {
foo: 'bar',
func: function() {
var self = this;
console.log("outer func: this.foo = " + this.foo);
console.log("outer func: self.foo = " + self.foo);
(function() {
console.log("inner func: this.foo = " + this.foo);
console.log("inner func: self.foo = " + self.foo);
})(); // IIFE
};
myObject.func();
Answer
function foo1() {
return {
bar: "hello"
};
}
function foo2()
{
return
{
bar: "hello"
};
}
This seems pretty harmless. But let’s look at what actually happens when we
invoke these 2 functions:
function foo2()
{
return; // JS ASI in Action!
// The lines below are dead/ unreachable code
{
bar: "hello"
};
}
const objOld = {
func1: func1,
var1: var1
};
console.log(objOld);
//=> { func1: [Function: func1], varl: 'abc' }
As the names of the object’s property and the variable are the same, you can
omit repeating the declaration and assignment:
const objPropertyShorthand = {
func1,
var1
}
console.log(objPropertyShorthand);
//=> { funcl: [Function: func1], varl: 'abc' }
Exercise:
The below function should return an object with below properties:
1. type: 'CHANGE_NAME'
2. name: <name_in_the_argument>
function onChangeName(name) {
// ---- Fill me -----
}
Answer:
Just return the object literal, as a small optimization, use object property
shorthand for name .
return {
type: 'CHANGE_NAME',
name // Object Property Shorthand
}
Destructuring Operator
The below example illustrates a new convenience feature of JavaScript,
Destructing Operator:
console.log(foo); //=> 42
console.log(bar); //=> true
One of the reasons why the community loves React is the fact that when they
learn React, they are learning more JavaScript than just framework specific
hooks and directives (e.g. ng-if ) . In that very spirit, I would encourage you
to further your exploration of this misunderstood language. Master JavaScript
and its ecosystem and you wouldn’t be daunted by any new front-end
frameworks coming in your way. Goodspeed!
Where to Go From Here
Functional Programming in JavaScript
Functional Programming (FP) seems to be the in thing lately. In the
discussion about Promise, I mentioned in passing that Promise is a Monad.
Interested to know more about this? I would recommend:
I love the above materials so much that I compiled my own notes here: Tomy
Jaya’s Composable Functional JS Notes