JavaScriptのナイスな文法テクニック集

JavaScriptのとってもナイスな文法テクニック集を発見したので紹介してみます。
以下は[Byte saving techniques](https://github.com/jed/140bytes/wiki/Byte-saving-techniques)の日本語訳です。

なお、イタリックは訳者(私だ)による追加です。


# Byte-saving Techniques

これはJavaScriptのコードから文字数を減らすための魔法のコレクションです。
主に[Twitterチャレンジ](https://gist.github.com/962807)を作成するための参考資料として書かれています。
新たなテクニックを発見したときは[@140bytes](http://twitter.com/140bytes)にフィードバックください。

## Arguments

### Use one-letter positional arguments, in alphabetical order

引数はできるだけ短くする必要があり、かつ再利用される可能性も高いので、意味で表すのではなく順序で表すのが最善です。
頭文字を使用すると、ひとつの関数の読みやすさが僅かに向上しますが、一貫して順序で表すことで全ての関数の読みやすさが向上します。

```javascript
	function(t,d,v,i,f){...} // before
	function(a,b,c,d,e){...} // after
```

### Test argument presence instead of length

指定個数の引数が渡されたかをチェックするにはinを使います。

```javascript
	arguments.length>1||(cb=alert) // before
	1 in arguments||(cb=alert)     // after
```

引数がtrueっぽい値であると決まっているなら、もう少し縮められます。

```javascript
	arguments[0]&&(cb=alert)       // after arguments[0]がtrueっぽい値ならOK
```

### Embed functionality within arguments

引数内で直接計算することで、デリミタを削減することができます。

```javascript
	a+=b<<1;x(a,1); // before
	x(a+=b<<1,1);   // after
```

### Reuse parenthesis of the function call

引数を取らない関数もありますが、その関数呼び出しの括弧を他の用途に流用できることは確定的に明らかです。
使用例は@snowlordの[逆ポーランド記法](https://gist.github.com/peterjaric/1276436)を参照してください。

```javascript
	((a=b.pop(),b.pop())+c+a); // before
	(b.pop(a=b.pop())+c+a);    // after
```

関数が実際に引数を取るかわからない場合は、その[.length](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/length)が0であるかを確認しましょう。

### setInterval and setTimeout hacks

setIntervalとsetTimeoutには、関数ではなく文字列を渡しましょう。

```javascript
	setInterval(function(){console.log("z")},100) // before
	setInterval('console.log("z")',100)           // after
```

第2引数を省略した場合、デフォルト値はブラウザの設定可能な最速間隔(最近のブラウザでは1ms)になります。

```javascript
	setInterval('console.log("z")',1) // before
	setInterval('console.log("z")')   // after
```

## Variables

### Use placeholder arguments instead of var

`var`を宣言するかわりに、引数で変数を定義しましょう。

```javascript
	function(a){var b=1;...} // before
	function(a,b){b=1;...}   // after
```

場合によっては`var`のほうが短くなることもあるので注意しましょう。各場合で正しい判断を下す必要があります。

```javascript
	function(a,b,c,d){b=1;c=2;d=3;...} // before
	function(a){var b=1,c=2,d=3;...}   // after
```

### Re-use variables where possible

一見不要になった変数を再利用することで、文字数を節約できます。

```javascript
	setTimeout(function(){for(var i=10;i--;)... }, a) // before
	setTimeout(function(){for(a=10;a--;)... }, a)     // after
```

### Assign wherever possible

変数割り当てはその値を返すので、割り当てと評価を同時に実行できます。
よい例が@jedの[JSONP](https://gist.github.com/jed/962814)で、createElementに文字列"script"が渡されています。

```javascript
	a=this.localStorage;if(a){...} // before
	if(a=this.localStorage){...}   // after
```

### Use an array to swap variables

無駄な変数宣言を避けるために、一時的な配列を使うことができます。

```javascript
	var a=1,b=2,c;c=a;a=b;b=c // before
	var a=1,b=2;a=[b,b=a][0]  // after
	var a=1,b=2;a=b^a^(b=a)   // after 役に立たないが役に立つ
```

数値の場合はさらに2バイト減らせます。

```javascript
	var a=1,b=2;a=[b,b=a][0]  // before
	var a=1,b=2;a+=b-(b=a)    // after
```

### Exploit coercion

暗黙の型変換はJavaScriptにとっての祝福であり呪いでもありますが、時には非常に便利です。
@jedの[pubsub](https://gist.github.com/jed/976046)では、sub時に負数をデクリメントし、その結果を文字列と結合して"someString-123"のような文字列を生成します。
pub時はマイナス記号を分割文字のハイフンとして使用し、元々の文字を復元しています。

### Choose small data format

必要なデータはしばしば配列やObjectで与えられますが、多くの場合これらの無駄はstringで置き換えることができます。
[Date.parse polyfill](https://gist.github.com/atk/1053863)は、普通はObjectで扱う変換テーブルをstringで扱う見事な例です。

## Loops

### Omit loop bodies

必要な処理を全てループの条件部分で実行できる場合、ループの本体は必要ありません。
@jedの[timeAgo](https://gist.github.com/jed/965606)関数を参照してください。

### Use for over while

forとwhileは同じバイト数ですが、forのほうがより多くの機能を使えます。

```javascript
	while(i--){...} // before
	for(;i--;){...} // after

	i=10;while(i--){...} // before
	for(i=10;i--;){...}  // after
```

forループでは2番目の引数も省略できます。falseっぽい値が入ってきたらループが修了します。

### Use index presence to iterate arrays of truthy items

配列の値が全てtrueっぽいとわかっているのであれば、直接値を参照することで文字数を節約できます。

```javascript
	for(a=[1,2,3,4,5],l=a.length,i=0;i<l;i++){b=a[i];...}
	for(a=[1,2,3,4,5],i=0;b=a[i++];){...}
```

### Use for..in with assignment to get the keys of an object

_for..inでキーを取得する。_

```javascript
	a=[];i=0;for(b in window)a[i++]=b // before
	a=[];i=0;for(a[i++]in window)     // after
	a=Object.keys(window)             // ES6 prototypeの値は返さない
```

さらに配列から数値に強制型変換することもできます。`i=a=[];for(a[i++]in window);`

### Use reverse loops where possible

列挙の順番が逆でもいいのであれば、文字数を多少減らすことができます。

```javascript
	for(a=0;a<x.length;a++)...     // before
	for(a=x.length;a--;)...        // after
```

### Use both for body and counting expression for multiple operations

_演算が複数ある場合、forの本体とカウンタ部分に分けて書く。_

```javascript
	for(i=3;i--;foo(),bar());   // before
	for(i=3;i--;)foo(),bar();   // before
	for(i=3;i--;bar())foo();    // after
```

### for..in will not iterate over false - use this to trigger iteration

for..inはObjectとstring以外の値、0やfalseっぽい値が渡されると、エラーを出さずループもせず次に進みます。

```javascript
	if(c)for(a in b)x(b[a]); // before
	for(a in c&&b)x(b[a]);   // after
```

## Operators

### Understand operator precedence

[演算子の優先順位](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Operator_Precedence)は熟読しておきましょう。

### Understand bitwise operator hacks

### Use ~ with indexOf to test presence

_存在チェックは~とindexOfをセットで使う。_

```javascript
	hasAnF="This sentence has an f.".indexOf("f")>=0 // before
	hasAnF=~"This sentence has an f.".indexOf("f")   // after
```

### Use , to chain expressions on one conditional line

_`,`を使えば1文で色々書ける。_

```javascript
	with(document){open();write("hello");close()} // before
	with(document)open(),write("hello"),close()   // after
```

### Use []._instead of undefined

`""._`、`1.._`、`0[0]`も動作しますが、[動作は遅く](http://jsperf.com/undefineds)なります。
`void 0`は`undefined`より早いですが文字数が長くなります。

### Remove unnecessary space after an operator

演算子の後には空白が必ずしも必要というわけではなく、しばしば削除可能です。

```javascript
	typeof [] // before
	typeof[]  // after
```

## Numbers

### Use ~~ and 0| instead of Math.floor for positive numbers

`~~`と`0|`はともに切り捨ての計算となります。
ただし`~`は`|`より優先順位が低いので、同じ結果になるとは限りません。

```javascript
	rand10=Math.floor(Math.random()*10) // before
	rand10=0|Math.random()*10           // after
```

2の累乗で割った商を求めたい場合は、ビットシフトだけで表現できます。

```javascript
	Math.floor(a/2) // before
	a>>1            // after

	Math.floor(a/4) // before
	a>>2            // after
```

### Use A + 0.5 | 0 instead of Math.round for positive numbers

_四捨五入するより+0.5して切り捨てた方が短い。_

```javascript
	Math.round(a) // before
	a+.5|0        // after
```

負数の四捨五入には+0.5ではなく-0.5とします。

```javascript
	Math.round(-a) // before
	-a-.5|0        // after
```

### Use AeB format for large denary numbers

`AeB`は`A*Math.pow(10,B)`と同じです。

```javascript
	million=1000000 // before
	million=1e6     // after
```

### Use A<<B format for large binary numbers

`A<<B`は`A*Math.pow(2,B)`と同じです。
@jedの[rgb2hex](https://gist.github.com/jed/983535)がよい例となります。

```javascript
	color=0x100000 // before
	color=1<<20    // after
```

### Use 1/0 instead of Infinity

Infinityと書くより短くなります。

```javascript
	[Infinity,-Infinity] // before
	[1/0,-1/0]           // after
```

### Use division instead of isFinite()

有限の数であれば、1を割ったらtrueっぽい数値が返ってきます。

```javascript
	if(isFinite(a)) // before
	if(1/a)         // after
```

### Exploit the "falsiness" of 0

数値を比較する場合、0にしてから比較した方が短くなることがよくあります。

```javascript
	a==1||console.log("not one") // before
	~-a&&console.log("not one")  // after
```

### Use ~ to coerce any non-number to -1,

_非数値に`~`を使うと-1になる。_
`-`と一緒に使えば、初期化されているいないに関わらずインクリメントすることができます。
これは@jedの[JSONP](https://gist.github.com/arlolra/986269)の実装で使われています。

```javascript
	i=i||0;i++ // before
	i=-~i      // after
```

`-`と`~`を逆にすることで、デクリメントすることもできます。

```javascript
	i=i||0;i-- // before
	i=~-i      // after
```

### Use ^ to check if numbers are not equal

_数値の場合、`!=`と`^`は結果が同じになる。_

```javascript
	if(a!=123) // before
	if(a^123)  // after
```

### Use number base for character to number conversion

`parseInt(n, 36)`は、大文字小文字を区別せずにアルファベットを数字にする最も短い書き方です。
これは@subzeyの[parseRoman](https://gist.github.com/subzey/1040240)関数で使われています。

### Use current date to generate random integers

@aemkeiの[Binary Tetris](https://gist.github.com/1672254#file_annotated.js)で使われています。

```javascript
	i=0|Math.random()*100 // before
	i=new Date%100        // after
```

注意：ミリ秒が変わらない可能性があるため、高速なループ中では使用禁止！

## Strings

### Prefer slice over substr over substring

`substring(start,stop)`よりも`substr(start,length)`よりも`slice(start,stop)`を使いましょう。
文字を最後まで取得するときは第二引数を省略します。
負数は使わないようにしましょう。
`s.substr(-n)`は後ろn文字を取得しますが、IE9では動作しません。
_IE11では動いたので、もう使ってもいいだろう_

### Split using ''

文字列から配列にするには`s.split('')`を使います。
残念ながら`s[i]`はIE9では動作しません。
_これもIE11では動いたので、使ってもいいだろう_

### Split using 0

区切り文字には数値を使ったほうが2バイト節約できます。
@jedの[timeAgo](https://gist.github.com/jed/965606)関数で使われています。

```javascript
	"alpha,bravo,charlie".split(",") // before
	"alpha0bravo0charlie".split(0)   // after
```

### Use the little-known .link method

Stringは実は[link](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/link)というビルトインメソッドを持っています。
@jedの[linkify](https://gist.github.com/jed/965606)関数で使われています。

```javascript
	html="<a href='"+url+"'>"+text+"</a>" // before
	html=text.link(url)                   // after
```

Stringには、他にもHTMLラッパーメソッドが幾つか[存在します](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String)。

### Use .search instead of .indexOf

1バイト短くなります。
正規表現は''で囲むかわりに//で囲みます。

注意：正規表現が正しくないと失敗します。'.'をそのまま/./にしてしまうと全ての文字にマッチし、'+'を/+/にすると構文エラーになります。

### Use .replace or .exec for powerful string iteration

`.replace`は第二引数に関数を渡せるので、多くの反復処理を記述することが可能です。
これは@jedの[templates](https://gist.github.com/jed/964762)や[UUID](https://gist.github.com/jed/982883)で使われています。

### Use Array to repeat a string

_反復文字列の作成にArrayが使える。_

```javascript
	for(a="",i=32;i--;)a+=0 // before
	a=Array(33).join(0)     // after
	a="0".repeat(32)        // ES6
```

## Conditionals

### Use && and || where possible

```javascript
	if(a)if(b)return c // before
	return a&&b&&c     // after

	if(!a)a=Infinity // before
	a=a||Infinity    // after
```

### Coercion to test for types

文字列型であるかを調べるには、`typeof x=='string'`ではなく`''+x===x`を使いましょう。
同様に数値型は`typeof x=='number'`ではなく`+x===x`とします。
`+x`はxを数値型かNaNにするので、数値型以外の値はfalseになります。

注意：どっかのバカチンがprototypeをいじくっていた場合、これは動かないでしょう。

`typeof x=='function'`のかわりに`/^f/.test(typeof x)`を使っている例が@tkissingの[template engine](https://gist.github.com/tkissing/1347239)で参照できます。

### Type-specific methods to test for types

型を調べる他の方法は、型固有のメソッドが使用可能かチェックすることです。
@adiusの[DOMinate](https://github.com/adius/DOMinate)などで使われています。
型固有で最も短いメソッドは以下のとおりです。

| Type     | Test      |
|:---------|:----------|
| String   | x.big     |
| Number   | x.toFixed |
| Array    | x.pop     |
| Function | x.call    |
| textNode | x.data    |

文字列比較よりも高速です。

注意：もしこれらのメソッドやプロパティが追加されてしまった場合、誤った結果になるでしょう。

## Arrays

### Use elision

配列の要素は不要であれば省略可能です。
@jedの[Router](https://gist.github.com/jed/964605)で現実的な例を確認可能です。

```javascript
	[undefined,undefined,2] // before
	[,,2]                   // after

	// 最後の,は無視されることに注意
	[2,undefined,undefined] // length is 3
	[2,,]                   // length is 2
```

undefinedを文字列型に変換すると空文字になります。
@aemkeiの[Digital Segment Display](https://gist.github.com/aemkei/1272408)で例を確認できます。

```javascript
	b="";b+=x // before
	b=[b]+x   // after
	// 実際これやるとb="undefined"になるんだがなんだろう
```

以下の例も便利です。

```javascript
	((b=[1,2][a])?b:'') // before
	[[1,2][a]]          // after
```

### Use coercion to do .join(',')

配列のセパレータは`,`であるため、`array.join(',')`は`''+array`と書けます。

注意：配列内にシングルクォートやObjectや配列があるときはうまく動きません。

```javascript
	''+[1,true,false,{x:1},0,'',2,['test',2]]
	// "1,true,false,[object Object],0,,2,test,2"
```

### String coercion with array literal []

_数値型を文字列型にするときは配列のほうが短い。_

```javascript
	''+1e3+3e7 // before
	[1e3]+3e7  // after
```

@jedの[UUID](https://gist.github.com/jed/982883)でこれを使っています。

### Use coercion to build strings with commas in them

_カンマ区切りの文字列は配列で作ると短い。_

```javascript
	"rgb("+(x+8)+","+(y-20)+","+z+")"; // before
	"rgb("+[x+8,y-20,z]+")";           // after
```

最初か最後の値が静的のときも配列にした方が短くなります。

```javascript
	"rgb(255,"+(y-20)+",0)"; // before
	"rgb(255,"+[y-20,"0)"];  // after
```

### Use Arrays as Objects

Objectを作る必要があるときは、既に宣言されている配列にプロパティを突っ込みましょう。
実のところ配列はObjectの一種に過ぎません。
プロパティ名が配列の組み込みプロパティと競合しないことだけ確認しておきましょう。

### Test if Array has Several Elements

`if(array.length>1)`は`if(array[1])`と書けます。

`array[1]`がfalseっぽい値だったときは動かないので、trueっぽい値であることがわかっている場合にのみ使用してください。
falseっぽい値だったときは、かわりに`if(1 in array)`と書くことができます。

## Regular Expressions

### Use shortcuts

/[0-9]/は/\d/、/[A-Za-z0-9_]/は/\w/、空白は/\s/と表すことができます。
大文字はその反転で、`\D`は数値以外にマッチします。
これらの正規表現は文字クラス内で使用可能です。
[\dA-F]は16進数文字列にマッチします。

/\b/は文字そのものではなく、単語の区切りにマッチします。
/\B/はその逆で、単語の区切り以外にマッチします。
_/\b/は/\w/以外の文字ではうまく動かない。_

その他の正規表現、`\Q`と`\E`などはしばしば動作しません。
正規表現の完全なリストは[Regular Expression Flavor Comparison](http://www.regular-expressions.info/refflavors.html)を参照してください。

/(a|b)/は/a|b/と同じです。
HTMLタグとマッチさせるには、/<[^>]*>/ではなく/<.*?>/を使います。
ただし、希に動作が異なる場合があります。

replaceする場合、マッチした文字列は`$&`、前後の文字列は`$\``と`$'`に入ってきます。
従って、/(x)/と`$1`を/x/と`$&`に変更可能です。

```javascript
	"abcdefg".replace(/^(cde)$/,"\1") // before
	"abcdefg".replace(/cde/,"$&")     // after
```

### Denormalize to shorten

/\d{2}/はスマートに見えますが、/\d\d/のほうが短いです。

### Don't escape

正規表現では、メタキャラクタを全てエスケープしなくても、正しく動作することがままあります。
たとえば/[[\\]-]/は、`]`はエスケープが必要ですが、`[`はエスケープが不要、そして`-`は文字クラス内の最後に書けばエスケープ不要です。

### eval() for a regexp literal can be shorter than RegExp()

可能であれば`new RegExp('\\d','g')`ではなく`/\d/g`を使いましょう。
実行時に正規表現を組み立てる必要があるならば、`eval()`の使用を検討してください。

```javascript
	r=new RegExp("\\\\{"+p+"}","g") // before
	r=eval("/\\\\{"+p+"}/g")        // after
```

### eval() around String.replace() instead of callback

出力にコールバック処理を行いたい場合、replace全体をevalで囲みましょう。
これは、マッチが複雑になればなるほど効果を増します。

```javascript
	x.replace(/./,function(c){m=m+c.charCodeAt(0)&255})  // before
	eval(x.replace(/./,'m=m+"$&".charCodeAt(0)&255;'))   // after
```

## Booleans

### Use ! to create booleans

真偽値は数値から作成します。

```javascript
	[true,false] // before
	[!0,!1]      // after
```

強制型変換も便利です。
数値型にするとtrueは1に、falseは0になります。
入力の条件にに対して2、1、0の3値を出力するプログラムは以下のように書けます。

```javascript
	x>7?2:x>4?1:0 // before
	+(x>7)+(x>4)  // after
```

minifierは[真偽値を置換することで文字数を削減](https://davidwalsh.name/javascript-booleans)します。

```javascript
	true === !0  // save 2 chars
	false === !1 // save 3 chars
```

## Functions

### Shorten function names

関数には短い別名を割り当てます。
複雑な場合はこれで高速化することもあります。

```javascript
	a=Math.random(),b=Math.random() // before
	r=Math.random;a=r(),b=r()       // after
```

### Use named functions for recursion

再帰はしばしばループより簡潔に書けます。
名前付き関数による再帰は@jedの[walk](https://gist.github.com/jed/964769)関数で使われています。

### Use named functions for saving state

関数に状態を保存したいときは、関数名を付けてコンテナとして使用します。
これは@jedの[JSONP](https://gist.github.com/jed/962814)で使われています。

```javascript
	function(i){return function(){console.log("called "+(++i)+" times")}}(0) // before
	(function a(){console.log("called "+(a.i=-~a.i)+" times")})              // after
	0,function a(){console.log("called "+(a.i=-~a.i)+" times")}              // another alternative
```

### Omit () on new calls w/o arguments

`new Object()`と`new Object`は同じです。

```javascript
	now = +new Date() // before
	now = +new Date   // after
```

### Omit the new keyword when possible

一部のオブジェクトではnewも必要ありません。

```javascript
	r=new RegExp(".",g) // before
	r=RegExp(".",g)     // after

	l=new Function("x","console.log(x)") // before
	l=Function("x","console.log(x)")     // after
```

### The return statement

英数字以外で始まる値を返す際は、`return`の後ろにスペースは必要ありません。

```javascript
	return ['foo',42,'bar']; // before
	return['foo',42,'bar'];  // after
	return {x:42,y:417}; // before
	return{x:42,y:417};  // after
	return .01; // before
	return.01;  // after
```

### Use the right closure for the job

即時実行が必要な場合は、適切なクロージャを選んで使用します。

```javascript
	;(function(){...})() // before
	new function(){...}  // after 何かをreturnしたいなら
	!function(){...}()   // after returnが不要
```

### Shorten function with Function

これは関数を複数定義しないといけない場合に便利です。
ただし引数を文字列で渡さなければならないため、必要か否かは使用時に判断してください。

```javascript
	function a(a){return a}
	function b(b){return b}
	function c(c){return c} //before

	var f=Function,
	a=f('a','return a'),
	b=f('b','return b'),
	c=f('c','return c')     //after
```

## In the browser

### Use browser objects to avoid logic

独自ロジックを書かずとも、ブラウザに専用メソッドが存在していることがあります。
URLのパースは@jedの[parseURL](https://gist.github.com/jed/964849)を、HTMLエスケープは@eligreyの[escapeHTML](https://gist.github.com/eligrey/1224209)で使われています。

### Use global scope

ブラウザでは`window`がグローバルなObjectなので、プロパティを直接参照可能です。
`document`や`location`はよく知られていますが、[innerWidth](https://gist.github.com/bmiedlar/981915)のような他のプロパティも同様です。

### A better way to getElementById()

27バイトも無駄があります。

```javascript
	document.getElementById('a').innerHTML = "foo"; // before
	a.innerHTML = "foo";                            // after
```

### Delimiters

他の文法で囲むことで`;`を省略できることがあります。

```javascript
	x=this;a=[].slice.call(arguments,1); // before
	a=[x=this].slice.call(arguments,1);  // after
```


# 感想

いやあ、かなり使えますよ、このリファレンスは。
みんなもどんどん使っていきましょう。

`division by zero gets you free internet points`の意味がわからなかった。
`Use ~~ and 0| instead of Math.floor for positive numbers`で`~`が使われてない。
`Use elision`のところが色々おかしい気がするのだがよくわからん。