The Good and Bad Parts of JS (according to Kyle Simpson)
Last time I summarized the good and bad parts of Javascript according to Douglas Crockford... Now I want to do the same according to Kyle Simpson, another Javascript expert I deeply respect. I gathered these opinions from several of Kyle Simpson's lecture on youtube and Linkedin Learning, especially his lectures on ES6, Coercion and Async Patterns.
Some Bad Parts
- The
new
keyword. Simpson advises to never use it, with only two exceptions: (1)new Regex("a*b", "i")
if you absolutely need dynamic regular expressions (other just use static/a*b/i
syntax) and (2) `new Date() because that's the only way to get the date. toString()
method on the Array & Object natives since they return misleading values. Simpson recommends writing your owntoString()
methods in these two cases... i.e. calling theJSON.stringify() method
as a customtoString()
method on the Object prototype.
Some Overated Parts
- The Arrow function is not widely needed... only for lexical scoping... i.e. binding
this
to outer scopeI disagree here but not all that strongly. I still use function declarations often for hoisting myself, but find concise arrow functions to be preferred whenever I reach for a function expression. And for callbacks, arrow functions are preferred. Simpson, himself, later on in the lectures I took this from, calls out several prominent use cases for the Arrow function, so this recommendation of his might be exaggerated.
- The "Death of Var"... in other words,
let
andconst
do not makevar
obsolete. It is still needed for cross scope accessibility const
is actually not widely needed... (Protecting objects/properties is needed, but not loose variables so most times what you actually want isObject.freeze
)
Some Good Parts
- Type Coercion: Simpson recommends using explicit coercion whenever possible:
String()
,Number()
,Boolean()
. Don't usetoString()
or "clever coercion" like+
,!!
let
is great for its auto-closure infor
loops and other block scopes (but still doesn't replace var)- Tagged Templates or Tag functions with Template strings... has led to many useful tag function libraries
function greet() {
return arguments;
}
var person = { name: "Jon", age: 28 };
// A tagged template is a function call that uses a template literal from which to get its arguments
greet`I'm ${person.name}. I'm ${person.age} years old.`;
// Arguments: [['I'm ', '. I'm ', ' years old.'], 'Jon', 28]
- Rest ("gather") and Spread operators make JS syntax much more declarative
- Default parameter values are awesome!! Default value can even be a function for logical defaults:
function foo(id = generateID()) {
//if foo is called with a user ID,
//then a new ID is generated and assigned for the new user
}
//OR enforce a psuedo type with manual exceptions
const required = (param) => throw "Missing required " + param;
function foo(id = required("id")) {}
Default parameters can also be used in combination with the Rest operator and can be used safely with a function that returns an empty Array or Object as a default object assignment instead of using the conventional default assignment using ||
.
// old way
function printObj(obj) {
let myObj = obj || {};
console.log(myObj);
}
// new way with default params
function defaultPrint(obj = {}) {
console.log(obj);
}
- Generators... they are basically a state machine with lazy evaluation since it pauses between calls.
// Can be coupled with while loops for endless generators:
function* uniqueID() {
while (true) {
yield Math.random();
}
}
var num = () => uniqueID().next().value;
num();
I love this take on generators. As long as we remember these generators are usually not pure functions we can still use them for a surprisingly large number of use cases. Since UI often tends to be best modeled as a finite state machine, generators can often model UI states very well.