JavaScript・jQueryの改修・高速化のためのメモ

たまにJavaScriptやjQueryなどの改修が入ったりすると忘れてしまうので、自分用のメモとして残しておきます。 
[JavaScriptコーディングベストプラクティス（高速かつ堅牢なコードを効率よく書くために）](http://www.amazon.co.jp/JavaScript%E3%82%B3%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0-%E3%83%99%E3%82%B9%E3%83%88%E3%83%97%E3%83%A9%E3%82%AF%E3%83%86%E3%82%A3%E3%82%B9-%E9%AB%98%E9%80%9F%E3%81%8B%E3%81%A4%E5%A0%85%E7%89%A2%E3%81%AA%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E5%8A%B9%E7%8E%87%E3%82%88%E3%81%8F%E6%9B%B8%E3%81%8F%E3%81%9F%E3%82%81%E3%81%AB-%E5%B0%8F%E6%9D%BE%E5%81%A5%E4%BD%9C/dp/4844361791)を参照しながらのメモになります。 
随時、この記事に追記予定です。

![JavaScriptコーディングベストプラクティス（高速かつ堅牢なコードを効率よく書くために）](https://qiita-image-store.s3.amazonaws.com/0/34020/526590da-7a9c-810d-03cb-faa8b342372b.jpeg)

# 高速化メモ JavaScript編

## スタイルシートは上に、JavaScriptは下に指定する

* JavaScriptファイルは読み込んだ後、通常はスクリプトを解析している間、他のファイルの読み込みをブロックする
* JavaScriptはページの上部に指定すると、このブロックによりロード時間が増加する場合がある
* スタイルシートはなるべく上に、JavaScriptファイルは下部にしていることで、ロード時間が短縮できる
* 画面描画に関係ないJavaScriptは、```</body>```の直前に書く

## $(document).readyを利用する

```js
$(document).ready(function(){
  // 通常DOMがすべて読み込まれた後に実行
})
```

```js
$(window).load(function(){
  // 画像などのファイルがすべてロードされた後に実行
})
```

* JavaScriptの起動は、通常DOMがすべて読み込まれた後に実行されるように記述すること
* $(window).load()を用いると、画像などのファイル群がすべてロードされた後になるため処理が遅れる
* 画像に対して操作を行う場合は、$(window).load()でハンドラを設定しなければならない
* ```</body>```タグの直前にscriptを入れる場合、$(docment).readyは必要ない

## CSSやJavaScriptは外部ファイルで作成する

* HTMLファイルは通常リロード時に毎回ダウンロードされる
* JavaScriptをインラインで記述せずに外部ファイルとして記述すると、これらのファイルはキャッシュされるので、ダウンロードサイズを削減できる

## ディレクトリ指定時には、"/"をつける

* HTML中にURLでディレクトリを指定する際は、かならず最後に"/"をつけること
* URIにアクセスした際、WEBサーバより ```http://hogehoge.com/directory/```へのリダイレクト要求が返信された後、再度サーバへアクセスする動作を行う
* リダイレクトの遅延が発生してしまい速度の低下を招く

# jQueryセレクタの高速化

## jQueryセレクタを高速化する方法

* jQueryは非常に簡単にDOM構造にアクセスできるが、内部的にはJavaScriptに変換されてDOMへのアクセスが行われている
* jQueryのDOMへのアクセスのスクリプトは高度に最適化されている（そのままでも下手なJavaScriptでコードを記述するよりも高速に動作する）

## DOM操作の回数を減らす

* DOMの操作を行う処理などを一度変数に格納して、1回で実行できるようにする
* 例）for文でappendメソッドを実行してみる

### 通常コード

```js
for(var i=0; i<500; i++){
  $('#hogehoge').append('<div></div>');
}
```

### 500個のdivを変数に入れてappendメソッドを実行する

```js
var html = '';
for(var i=0; i<500; i++){
  html += '<div></div>';
}
$('#hogehoge').append(html);
```

## 配列をforで回す時は、array.lengthも変数格納

コメント頂いた通り、配列をfor文で回すときはarray.lengthも変数格納することで高速化につながるそうです。

```js
var hoge = new Array("hoge01", "hoge02", "hoge03");
var hoge_length = hoge.length;

for (var i = 0 ; i < hoge_length ; i++){
  alert(hoge[i]);
}
```
## jQueryオブジェクトをキャッシュする

* jQueryではセレクタで指定したDOM構造をjQueryオブジェクトと呼ばれるjQueryで扱えるオブジェクト形式に変換している
* 頻繁に操作を行うjQueryオブジェクトは一度変数に保存しておいて使い回すこと
* 変数にキャッシュすることでパフォーマンスの改善を図ることができる

### 通常コード

```js
for(var i=0; i<100; i++){
  $('a.hoge[rel~="nofollow"]').css('color','red');
}
```

### jQueryオブジェクトを変数にキャッシュ

```js
var rel = $('a.hoge[rel~="nofollow"]');
for(var i=0; i<100; i++){
  rel.css('color','red');
}
```

## メソッドチェーンを活用する

* jQueryでは同一のjQueryオブジェクトへの複数のメソッドを適応する場合、個別にメソッドを適応するのではなく、メソッドチェーンを利用することで高速化を図ることができる

### 通常コード

```js
for(var i=0; i<100; i++){
  $('a.hoge[rel~="nofollow"]').css('color','red');
  $('a.hoge[rel~="nofollow"]').css('color','blue');
  $('a.hoge[rel~="nofollow"]').css('color','yellow');
  $('a.hoge[rel~="nofollow"]').css('color','black');
  $('a.hoge[rel~="nofollow"]').css('color','gray');
}
```

### メソッドチェーンを活用

```js
for(var i=0; i<100; i++){
  $('a.hoge[rel~="nofollow"]')
  .css('color','red')
  .css('color','blue')
  .css('color','yellow')
  .css('color','black')
  .css('color','gray');
}
```

## id属性を活用する

* JavaScriptではDOMへのアクセスの際にid属性で検索するのが最も高速
* jQueryでも同様にidセレクタで記述するとパフォーマンスが向上する
* コーディングと担当が別々の場合は、極力id属性を多用するようにすり合わせが必要

### 通常コード

```js
for(var i=0; i<100; i++){
  $('.hoge')
}
```

### id属性を活用

```js
for(var i=0; i<100; i++){
  $('#hoge')
}
```

## classセレクタに要素名を付ける（IE6,7のみ）

* idセレクタが利用できず、classセレクタを利用する場合は要素名をつけることで高速化を図ることが可能
* IE6とIE7のみ効果がでる（[jQueryのclassセレクタに要素名を付ける](http://blog.webcreativepark.net/2014/12/02-013527.html)）参照
* コメントを頂いた方々の意見とto-Rの西畑さんが記事にされていたため「[jQueryのclassセレクタに要素名を付ける](http://blog.webcreativepark.net/2014/12/02-013527.html)」

完全に読み落としと記載漏れでした。申し訳ございませんm(__)m
誤った知識共有失礼致しました。

### 通常コード

```js
for(var i=0; i<100; i++){
  $('.hoge')
}
```

### classセレクタに要素名を付ける

```js
for(var i=0; i<100; i++){
  $('ul.hoge')
}
```

## 配列からの取り出しはeachよりforを使う

* jQueryのeachメソッドは繰り返し処理をするためのものですが、forでできるものは積極的にforを使用する

### 通常コード

```js
array = [1,2,3,4,5];
$.each(array, function(h){
  array[h];
}
```

### forを使用

```js
array = [1,2,3,4,5];
for(var h=0; h<array.length; h++){
  array[h];
}
```

## シンプルなセレクタになるように心がける

* セレクタを構成する要素が少なければ少ないほど要素検索のプロセスが少なくなり、高速化することができる

## 要素を参照する時は、範囲を指定する

* 参照する要素が存在する範囲（要素）を指定することで、その対象に要素を探すため処理が早くなる
* 注意点は、FriefoxやIEでは実感できないが、webkit系では処理が早くなる
* 個人的には、さらに変数に格納する

### 通常コード

```js
$('.canvas');
```

### 範囲を指定する

```js
$('.canvas, #element');
```

## findメソッドを活用する

* IE6やIE7で高速化を図りたい場合や、それ以外のブラウザでもjQueryの独自セレクタを利用したい場合は、findメソッドを利用することで高速化することができる
* セレクタ内のスペースによるセパレートは内部では分割され、それぞれのfindメソッドが適応される
* ただしquerySelectorメソッドが適応される場合より速度が劣るので注意

### findメソッドの活用

```js
for(var i=0; i<100; i++){
  $('body').find('li:first').find('a')
}
```