厳密等価演算子(===)の使用を優先する
JavaScriptには2種類の等価演算子が存在します:===/!==と==/!=です。一般的に推奨されるのは前者の厳密な比較演算子です。
"2つのオペランドの型と値が完全に一致する場合、===比較の結果は真となります。"—JavaScript: The Good Parts
しかし、==や!=を使用すると、異なる型のオペランドを比較する際に問題が発生します。この場合、JavaScriptは値の型変換を試みますが、意図しない結果を引き起こす可能性があります。
eval関数の使用を避ける
JavaScriptのeval関数は、コンパイラへのアクセスを提供します。文字列引数を渡すことで、その文字列を実行した結果を得ることができます。
これはパフォーマンスを大幅に低下させ、またセキュリティ上の大きなリスクを引き起こします。eval関数の使用は可能な限り避けるべきです。
コードの省略記法を避ける
技術的には、多くのブラウザは中括弧やセミコロンを省略したコードでも正しく解釈できます。
if(someVariableExists)
x = false
しかし、次のコードを考えてみましょう:
if(someVariableExists)
x = false
anotherFunctionCall();
これは次のコードと等価であると誤解されるかもしれません:
if(someVariableExists) {
x = false;
anotherFunctionCall();
}
残念ながら、これは間違いです。実際の意味は次のようになります:
if(someVariableExists)
x = false;
anotherFunctionCall();
インデントが中括弧の機能を模倣していることに注意してください。これは非常に危険な習慣であり、避けるべきです。中括弧を省略できるのは1行のコードの場合のみですが、それでも議論の余地があります。
if(2 + 2 === 4) return 'nicely done';
将来のことを常に考える
将来、このif文にさらにコマンドを追加する必要が生じた場合、どうすればよいでしょうか?コードを書き直すしかありません。この問題の教訓は、省略記法には慎重であることです。
JSLintの活用
JSLintはDouglas Crockfordが作成したデバッガです。スクリプトをコピーするだけで、コード中の明らかな問題やエラーを素早くスキャンします。
"JSLintはJavaScriptソースコードを受け取り、スキャンします。問題が見つかれば、問題の説明とソースコード内の概略位置を返します。問題はしばしば構文エラーですが、そうとは限りません。JSLintはスタイルや構造上の問題もチェックします。コードが正しいかどうかを証明するものではありませんが、問題を見つけるための追加の目として役立ちます。"—JSLintドキュメント
スクリプトの作成を終える前にJSLintを実行することで、愚かな間違いを犯すことがないようにできます。
スクリプトをページの下部に配置する
このテクニックは以前の記事でも推奨しました。ここでも非常に適切なため、その情報をそのまま貼り付けます。
このベストプラクティスの主な目標は、ユーザーにできるだけ速くページをロードさせることです。スクリプトを読み込むと、ブラウザはファイル全体が読み込まれるまで処理を続けられません。そのため、ユーザーはより長い時間待たなければなりません。
JSファイルの目的が機能の追加(例えばボタンクリック時の処理)のみである場合は、bodyの終了タグの直前にそれらのファイルを配置してください。これは確実なベストプラクティスです。
より良い方法
<p>And now you know my favorite kinds of corn. </p>
<script type="text/javascript" src="path/to/file.js"></script>
<script type="text/javascript" src="path/to/anotherFile.js"></script>
</body>
</html>
forループの外で変数を宣言する
長いfor文を実行する際、インタープリタに必要な作業だけを行わせましょう。例えば:
悪い例
for(var i = 0; i < someArray.length; i++) {
var container = document.getElementById('container');
container.innerHtml += 'my number: ' + i;
console.log(i);
}
上記のコードでは、各反復で配列の長さをチェックし、DOMツリーをたどって"container"要素を見つける必要があります—効率が悪いです!
良い例
var container = document.getElementById('container');
for(var i = 0, len = someArray.length; i < len; i++) {
container.innerHtml += 'my number: ' + i;
console.log(i);
}
文字列結合の最適化
配列やオブジェクトを反復処理する際、常に使えるfor文を使用する必要はありません。仕事を完了する最速の方法を見つけましょう。
var arr = ['item 1', 'item 2', 'item 3', ...];
var list = '<ul><li>' + arr.join('</li><li>') + '</li></ul>';
"テストベンチマークであなたを煩わせません;私を信じてください(または自分でテストしてください)—これはこれまでで最速の方法です!"
— James Padolsey, james.padolsey.com
ネイティブメソッド(例えばjoin())を使用することは、抽象レベルの背後で何が起こっているかを気にせず、通常、非ネイティブメソッドよりもはるかに高速です。
グローバル変数の最小化
"グローバルなものを単一の名前空間にカプセル化することで、他のアプリケーション、コンポーネント、コードライブラリとの干渉の可能性を大幅に減らすことができます。"— Douglas Crockford
var name = 'jeffrey';
var lastname = 'Way';
function doSomething() {...}
console.log(name); // Jeffrey -- or window.name
より良い方法
var DudeNameSpace = {
name: 'Jeffrey',
lastname: 'Way',
doSometing: function() {...}
}
console.log(DudeNameSpace.name); // Jeffrey
グローバルな「足跡」を「DudeNameSpace」という奇妙な名前のオブジェクトに減らしたことに注意してください。
コードにコメントを追加する
最初は不要に思えるかもしれませんが、私に従ってください。あなたはできるだけ良いコメントをコードに追加したいと考えます。数ヶ月後にプロジェクトに戻ったらどうなるでしょうか?各行のコードの意図を簡単に思い出せないかもしれません。または、同僚があなたのコードを修正する必要がある場合はどうなるでしょうか?常に、常にコードの重要な部分にコメントを追加してください。
// 配列をループして各名前を表示する
for(var i = 0, len = array.length; i < len; i++) {
console.log(array[i]);
}
プログレッシブエンハンスメントの採用
常にJavaScriptが無効になっている場合を考慮してください。おそらく「ほとんどのウェブサイトの読者はJavaScriptを有効にしているので、心配しない」と思うかもしれません。しかし、これは大きな間違いです。
JavaScriptを無効にした場合のスライダーがどのようになるか見たことがありますか?(Web開発者ツールバーをダウンロードして確認してください。)サイトが完全に壊れる可能性があります。経験則として、サイトを設計する際はJavaScriptが無効になっていることを想定してください。そうすれば、ウェブページのレイアウトを段階的に強化し始めることができます!
setInterval/setTimeoutに文字列を渡さない
次のコードを考えてみましょう:
setInterval(
"document.getElementById('container').innerHTML += 'my new number: ' + i", 3000
);
このコードは低速であり、eval関数と同じ動作をします。setIntervalとsetTimeoutには決して文字列を渡さないでください。代わりに関数名を渡してください。
setInterval(someFunction, 3000);
with文の使用を避ける
最初の見た目では、with文は賢いアイデアのように思えます。基本概念は、深くネストされたオブジェクトへのアクセスにショートカットを提供することです。例えば...
with (being.person.man.bodyparts) {
arms = true;
legs = true;
}
代わりに次のように書く
being.person.man.bodyparts.arms = true;
being.person.man.bodyparts.legs = true;
残念ながら、いくつかのテストの後、このショートカットは新しいメンバーを設定する際に非常に悪いパフォーマンスを示します。代わりにvarを使用してください。
var o = being.person.man.bodyparts;
o.arms = true;
o.legs = true;
オブジェクトリテラルの使用
JavaScriptにはオブジェクトを作成する多种の方法があります。より伝統的な方法は「new」コンストラクタを使用することです:
var o = new Object();
o.name = 'Jeffrey';
o.lastname = 'Way';
o.someFuncion = function() {
console.log(this.name);
}
しかし、この方法は「悪い習慣」と見なされています。代わりに、より堅牢なオブジェクトリテラルメソッドを使用することをお勧めします。
より良い書き方
var o = {
name: 'Jeffrey',
lastName: 'Way',
someFunction: function() {
console.log(this.name);
}
};
空のオブジェクトを作成したいだけの場合、{}が役立ちます。
var o = {};
"オブジェクトリテラルにより、多くの機能をサポートするコードを記述し、コードの実装者にとって依然として比較的直感的なものにすることができます。コンストラクタを直接呼び出したり、関数に渡されるパラメータの正しい順序を維持したりする必要はありません。"—dyn-web.com
配列リテラルの使用
これは新しい配列を作成する場合にも適用されます。
まあまあの書き方
var a = new Array();
a[0] = 'Joe';
a[1] = 'Plumber';
より良い書き方
var a = ['Joe', 'Plumber'];
"JavaScriptの一般的な間違いは、配列が必要なときにオブジェクトを使用したり、オブジェクトが必要なときに配列を使用したりすることです。ルールは単純です:プロパティ名が小さな連続した整数である場合は配列を使用してください。それ以外の場合は、オブジェクトを使用してください。"—Douglas Crockford
複数の変数宣言を簡潔にする
var someItem = 'some string';
var anotherItem = 'another string';
var oneMoreItem = 'one more string';
より良い書き方
var someItem = 'some string',
anotherItem = 'another string',
oneMoreItem = 'one more string';
非常に明確です。速度向上があるかどうかはわかりませんが、コードをより簡潔にします。
セミコロンを常に使用する
技術的には、ほとんどのブラウザは一部のセミコロンを省略することを許可します。
var someItem = 'some string'
function doSomething() {
return 'something'
}
それでも、これは非常に悪い習慣であり、より大きな問題を引き起こし、問題の特定もより困難になります。
より良い書き方
var someItem = 'some string';
function doSomething() {
return 'something';
}
for...inループの正しい使い方
オブジェクト内のメンバーを反復処理する際、メソッド関数も取得される可能性があります。この問題を解決するために、常にif文でコードをラップして情報をフィルタリングしてください。
for(key in object) {
if(object.hasOwnProperty(key)) {
... then do something...
}
}
—JavaScript: The Good Parts, Douglas Crockford著より引用
Firebugのタイマー機能を活用する
操作がどれくらい時間がかかるかを検出する簡単な方法が必要ですか?Firebugの「timer」機能を使用して結果を記録してください。
function TimeTracker() {
console.time("MyTimer");
for(x=5000; x > 0; x--){}
console.timeEnd("MyTimer");
}
継続的な学習の重要性
私はWeb開発ブログのスーパーファンですが(このブログも!)、ランチや寝る前の時間には、ブログは本の代わりにはなりません。常にベッドサイドテーブルにWeb開発の本を置いてください。以下は私のお気に入りのJavaScriptの本です。
- オブジェクト指向JavaScript
- JavaScript:言語精髄
- jQuery 1.3の学習
- JavaScriptの学習
何度も読んでください。私はまだ読んでいます!
即時実行関数の活用
関数を呼び出すよりも、ページのロード時や親関数の呼び出し時に自動的に実行される関数の方が簡単です。関数を括弧で囲み、追加の括弧を追加することで、本質的にその関数を呼び出すことができます。
(function doSomething() {
return {
name: 'jeff',
lastName: 'way'
};
})();
ライブラリより生のJavaScriptが速い
JavaScriptライブラリ(jQueryやMootoolsなど)は、特にAJAX操作の場合、多くのコーディング時間を節約できます。それでも、常にライブラリの実行速度は生のJavaScriptコード(コードの正しさを仮定)よりも遅いことを忘れないでください。
jQueryのeachメソッドは反復処理に非常に優れていますが、ネイティブのfor文を使用する方が常に速いです。
JSON.parseの利用
JavaScript 2には組み込みのJSONパーサーがあるはずですが、この記事が書かれた時点では、まだ自分で実装する必要があります。JSONの作成者であるDouglas Crockfordは、使用できるパーサーを実装しています。ここからダウンロードできます。
このスクリプトをインポートするだけで、.jsonファイルを解析するための新しいJSONグローバルオブジェクトが得られます。
var response = JSON.parse(xhr.responseText);
var container = document.getElementById('container');
for(var i = 0, len = response.length; i < len; i++) {
container.innerHTML += '<li>' + response[i].name + ' : ' + response[i].email + '</li>';
}
"language"属性の廃止
数年前、scriptタグ内に「language」属性が一般的でした。
<script type="text/javascript" language="javascript">
...
</script>
しかし、この属性は早くから廃止されており、使用しないでください。