Xah JavaScript Style Guide for Functional Programers
Xah's JavaScript style guide, for functional programing. Ordered roughly from most important to less.
Code Formatting
use deno fmt
Never use var
Never use var
. It is from early days of JavaScript. It has complex variable scope
[see var Name Scope]
, and complex name-hoisting behavior.
[see var Declaration Order (Name Hoisting)]
Always Declare Variable
Never have undeclared variable such as:
x = 3
.
Undeclared variables becomes properties of global object.
[see JavaScript: Global Variable]
.
Never Use ==
Never use double equal ==
.
The ==
does type conversion implicitly, which
returns true
for [] == ""
, etc.
Use triple equal ===
instead.
[see Equality]
Never Use for-in Loop
When you use
for-in Loop
,
for (x in obj) {body}
,
it goes thru the Prototype Chain. That's almost never what you want.
To go thru properties, use: Object.keys or Object.getOwnPropertyNames then use Array.prototype.forEach [see List Properties]
Never Use “with” Statement
The with
statement creates semantic ambiguity of code inside its curly brackets,
if local variable are declared using var
, it can mean the property of a object.
For example,
const jj = {x:4}; with (jj) { var x = 3; // x is meant to be local variable } console.log( jj ); // { x: 3 } // jj.x is changed
This is tricky, because
the variable
x
can mean multiple things.
If y
has a property x
, then x
means y.x
,
else it means the local variable x
.
You have to watch out whenever you use a local variable. But you may
not know what property y
has.
The problem goes away if you use let
to declare local variable.
const jj = {x:4}; with (jj) { let x = 3; } console.log( jj ); // { x: 4 } // jj.x is not changed
Never Use the Delete Operator
You should NEVER use the “delete” Operator .
- Do not use
delete
operator to delete array element. That results a Sparse Array . Use Array.prototype.splice to delete elements in array. - Avoid deleting or adding properties to object. Because, due to implementation, adding/deleting properties is inefficient. Instead, change the value to
null
. - Delete operator should only be used to delete object property. But actually, use Reflect.deleteProperty instead, because it has more sensible return value.
Never Use the Arguments Object
Don't use the arguments
object. You never need it. It makes code hard to understand, and has optimization problems. [see JavaScript: Function's “arguments” Object]
Use:
Never Use the Property named “constructor”
Never use the property key "constructor"
. Because its value can be anything.
Every function f has a property key "prototype"
.
[see Property Key "prototype"]
The value of it by default is {"constructor":f}
(that is, a object with a property key "constructor"
, with value of the function itself).
f.prototype.constructor
can be changed anytime by user.f.prototype
can also be changed anytime by user.
Never use the instanceof Operator
Never use the instanceof Operator . Because, what it actually does may not be what you expect, and there are better ways to do what you want.
obj instanceof f
is basically the same as f.prototype.isPrototypeOf(obj)
.
Lots of things can go wrong, because:
- The value
f.prototype
can be changed anytime. - Parent of object can also change anytime.
To find a object's subtype, use
Object.prototype.toString.call(x)
.
[see Determine Type of Object]
To determine if a object is in the Prototype Chain of another, use Object.prototype.isPrototypeOf .
Never Use Object Constructor “Object()”
Never use the
Object Constructor
Object(…)
to create a object,
because its behavior is complex. Use it only to convert a primitive value to object type.
To create object,
use
Object Literal Expression
{…}
, or use
Object.create
.
Avoid Using “eval()”
Using eval is sort of meta programing. But it has several problems.
- It is a security risk. For example, user's arbitrary input could be evaluated.
- It is bug prone. It is hard to debug and tell what it is doing, because the code is not known until run-time.
- It is slow. Because JavaScript has to parse it and run it at run time.
Never Use Keyword “this”
Never use this
keyword. Because, its value is dependent on calling context in a complex way.
[see this Binding]
Use Object.create
See also: Use Object.create to Emulate Constructor
Douglas Crockford, said he stopped using this
and new
.
[see Douglas Crockford the Better Parts: the Bads Parts Reconsidered]
Never Use Operator 「new」
Avoid using new F
, because its behavior is extremely complex, and drags in all the extremely other complex parts, the keyword this
, the function prototype property, and constructor property.
[see Operator “new”]
Instead, write a function that returns a object, and or use Object.create. This way, you can more simply and reliably specify parent object or the Prototype Chain. [see Use Object.create to Emulate Constructor]
Never Use Exceptions
As a programing style in general, you might consider avoid using the {Throw Try Catch Finally}. [see Throw Try Catch Finally]
Because, they are implicit goto, and are prone to be abused. Meaning, it makes it hard to understand the program flow.
Write your program to handle error cases explicitly, locally.
For more detail, See: Why I Hate Exceptions .
Never Use Accessor Properties
Getter/Setter Properties are complex, and are not necessary. They are methods pretending to be properties. Just define methods explicitly if you need to. This way, it is explict what the code is doing.
Always Use Semicolon
Always use semicolon. Omitting semicolon creates hard-to-find bugs.
const f = function() { return 3; } // bad semicolon omission (function() { return 4; })(); // TypeError: (intermediate value)(...) is not a function
[see Semicolon]
Never use Function.prototype.Call, Function.prototype.Apply
See Function Call, Apply, Bind.
Use Reflect.apply instead, because it avoids JavaScript complex Prototype Chain, and makes the code clearer.
Never Use Keyword “function” to Define a Function
Functions defined by keyword function
has the complex
this Binding
and complex
“arguments” Object.
Also the complex hoisting behavior and scope issues.
See
Function Declaration vs Function Expression
.
Always use Arrow Function. Arrow function do not have thisBinding nor argument object, nor hoisting behavior nor nesting scope problems.
Never Use Keyword “class”
The Class is a syntax shortcut for JavaScript's prototype object system, which drag you into all the bad things about it.
Program functionally. Just use Arrow Function
Naming of Things
- function names start with
f_
- variable names start with
x
- global variable are
ALL_CAPS
- parameter names start with capital letter e.g.
FirstCap