Readability, Idioms and Compression Tolerance
ReadabilityIdioms and Compression Tolerance
About
many a transformation to this shape.
From
- JS idioms collection
- tasteful code
- style guide
-
- current shape
code readability ,compression tolerance, code as data
My JS style
Agenda
- Readability
- Code Formatting
- Compression Tolerance
- Idioms
- Getting Rid of Flow Control
To the Inquisitors
- My Own Idiosyncratic Style
- Blending in is more important
Not the accepted dogma
Seven Pillar of Pretty Code #1 => Blend in
If it doesn't fit your style, don't use them.
You've been warned.
What do you mean readable?
- Easy to scan
- Consistent
- Lean
- Fits in my buffer
More experience => More code on a single line
More Scanability
- Blend In
- Bookish
- Disentangle Code Block
- Comment Code Block
- Declutter
- Make Alike Look Alike
- Overcome Indentation
var statement
var top = 43.2,
left = 2
width = 10,
height = 13;
var point = {
top : 43.2,
left : 2
width : 10,
height : 13;
};
Better
var top = 43.2
, left = 2
, width = 10
, height = 13
, point = { top : 43.2
, left : 2
, width : 10
, height : 13
}
;
- Better typo detection
- Better continuity
- Single line edit => Better merge and diff
Objects and Arrays
var sizes = [ { width = 10
, height = 13
}
, { width = 40
, height = 23
}
]
A Note on Arrays of Arrays
// What's in sizes
var sizes = [ ["a", 2, 3], ["b", 4, 5] ["c", 4, 5] ];
Answer: [undefined]
Nasty bug that can creep on you
Solved!
// What's in sizes
var sizes = [ ["a", 2, 3]
, ["b", 4, 5]
["c", 4, 5]
];
Function Calls
ajax.POST( '/my/absolute/resources', { param1 : 32 , other : "Sender is "+ sender.name }, myData, function (success, data) {
if (!success) alert( "A problem" )
// Do something
}
);
Better
ajax.POST( '/my/absolute/resources'
, { param1 : 32
, other : "Sender is "
+ sender.name
}
, myData
, function (success, data) {
if (!success) alert( "A problem" )
// Do something
}
);
Advantages of comma-in-front
- Easier typo detection
- Nicer blocks
- Better flow
- One line to edit
- Better merging and diff
Acquired taste
Lots to cover, onward
Idioms
Before moving to compression tolerance
Some idioms
Knowing the idioms associated with a programming language and how
to use them is an important part of gaining fluency in that language.
In the Beginning...
if (arguments.length == 0) {
return true;
} else {
return false;
}
- So many levels of wrong
- Prompted this talk
- So much noise
Idiomatic JS
return !!arguments.length;
// if (arguments.length == 0) {
// return true;
// } else {
// return false;
// }
- Everything is defined
- no ambiguity
- Readable
Use Literals
// new Array(3), new Array(3,2,1)
var array = [3,2,1]
// new Object() ...
, object = { name : 'Name'
, desc : 'Description'
}
new Array(3) controls length
For RegExp Too
// Part of a string.format method
var capture = /\{(\d+)\}/
// Vs
var capture = new RegExp('\\{(\\d+)\\}')
Color coding looks better
Module
!function (){
// Your module
}();
Better concat minify when munging
Array Cloning
var clone = arr.slice(0);
Vs Loops
Also arguments
Arguments to array
function (/*Variadic args */) {
var args = [].slice.apply( arguments, 0 )
}
// Same method as Array.prototype.slice
Array of strings
var strs = ['Words', 'is', 'a', 'phrase']
var strs = 'Words in a phrase'.split(' ')
var strs = $W('Words in a phrase')
Multistring Condition
var isFavorite;
if (color === "red" || color === "blue" || color === "green" ) {
isFavorite = true;
}
else {
isFavorite = false
}
return isFavorite
Multistring Condition
return ~'red blue green'.indexOf(color) )
return /^(?:red|blue|green)$/.test(color)
return color.match(/^(?:red|blue|green)$/)
return ~$W('red blue green').indexOf(color)
Optimized Short While
var l = items.length
while (l--) {
process( items[l] )
}
RegExp Looping
String.prototype.format = function ( /* args */ ) {
var args = arguments;
return this.replace( /\{(\d+)\}/g
, function (full, idx) {
return args[idx];
}
)
}
'Hello {0}, How{1}'.format( 'Bob', ' you doin')
// => Hello Bob, How you doin
Cyclomatic Complexity
Getting rid of
if
Default Operator ||
function ( x ) {
if (!x) { x = 0 ;}
// vs
x = x || 0;
// x || ( x = 0 );
}
Guard Operator &&
function (success, data, cb ) {
cb && cb( success, data)
// vs
if ( cb ) cb( success, data)
}
Ternary Operator
obj[ visible ? 'show' : 'hide' ]()
// vs
if ( visible ){
obj.show()
}
else {
obj.hide()
}
Ternary For Pattern Matching
// computedType
var xtds = this['extends']
return ( String.is(type) ? type
: Array.is(type) ? type.map(toComputedType)
: Object.is(type) ? type.linkTo()
: 'extends' in this ? (Array.is(xtds) ? xtds[0]
: xtds
).computedType()
: 'any'
);
Replacing Switch
return ( { visa : /^4[0-9]{12}(?:[0-9]{3})?$/ // Visa: length 16, prefix 4, dashes optional.
, mastercard : /^5[1-5][0-9]{14}$/ // Mastercard: length 16, prefix 51-55, dashes optional.
, americanexpress : /^3[47][0-9]{13}$/ // American Express: length 15, prefix 34 or 37.
}
[$('.menuselected').attr('id')] // Pick one
|| /^4[0-9]{12}(?:[0-9]{3})?$/ // or Default
Return Early
function fib(n){
if (n > 1) {
return fib(n-1) + fib(n-2)
}
else{
return n;
};
}
function fib(n){
if (n <= 1) return n // Exit condition first
return fib(n-1) + fib(n-2);
}