jQuery3.0 アップグレードガイド

2016/05/20に[jQuery 3.0のリリース候補版](https://blog.jquery.com/2016/05/20/jquery-3-0-release-candidate-released/)が出てたので[アップグレードガイド](https://jquery.com/upgrade-guide/3.0/#jquery-core-3-0-upgrade-guide)を見てみます。

# Overview

jQuery3.0ではコードのクリーンアップとかバグ修正とかDeprecatedなコードの削除とか色々やってるよ。

# Browser Support

・IE 9以降
・Chrome/Edge/Firefox 最新のひとつ前のバージョンまで
・Opera 最新版のみ
・iOS 7以降
・Android 4.0以降

# jQuery Migrate Plugin

[移行プラグイン](https://github.com/jquery/jquery-migrate/#README)を用意してるから、以下の1行入れとけば1.12、2.2と互換するよ。

```javascript
<script src="https://code.jquery.com/jquery-3.0.0.js"></script>
<script src="https://code.jquery.com/jquery-migrate-3.0.0.js"></script>
```

それ以前はjQuery Migrate 1.x Pluginとか使ってどうにかしろ。

# Summary of Important Changes

たくさん変更があるけど、ほとんどの場合は何もしなくても動くはずだよ。
・Breaking change
　非互換の変更だから動かなくなることがあるけど、ほとんどはエッジケースのはずだよ。
・Feature
　新機能だから影響しないはずだけど、もしかしたら何かあるかも。
・Deprecated
　まだ存在してるけど非推奨だからそのうち削除されるよ。

移行プラグインを使うと、これらを使ってるところを検出できるよ。

## Ajax

### Breaking change: Special-case Deferred methods removed from jQuery.ajax

$.ajax()のjqXHRが持ってた独自実装success、error、completeを削除したよ。
今後はDeferredのスタンダードdone/fail/alwaysか、もしくはPromises/A+準拠のthen/catchを使ってね。

### Breaking change: Cross-domain script requests must be declared

`$.ajax()`や`$.get()`でクロスドメインのスクリプトをリクエストするときは、明示的に`dataType:"script"`を指定しないと動かないよ。
`$.getScript()`はスクリプトなのが明らかだから指定する必要はないよ。

### Breaking change: Hash in a URL is preserved in a jQuery.ajax() call

`$.ajax()`はURLのハッシュを無視しなくなったよ。
サーバ側が未対応かもしれないから注意だよ。

### Feature: New signature for jQuery.get() AND jQuery.post()

`$.get()`と`$.post()`に、`$.ajax()`と同じく詳細なパラメータを連想配列で渡せるようになったよ。

## Attributes

### Breaking change: .removeAttr() no longer sets properties to false

checked、selected、readonlyみたいなtrue/false属性にremoveAttrは効かなくなるよ。
`.removeAttr("checked")`みたいなのは間違いだから、正しく`.prop("checked", false)`ってやってね。

### Breaking change: select-multiple with nothing selected returns an empty array

これまで`<select multiple>`で要素がひとつでも入っていた場合は値の配列、未選択だった場合はnullが返ってきてたけど、不便だから未選択の場合は空の配列が返ってくるようにしたよ。

### Feature: SVG documents support class operations

jQueryはSVGに対応したことはないはずなんだけど、これまで何故かだいたい動いてたよ。
jQuery3ではSVGで.addClass()と.hasClass()が動くようにしたよ。

### Deprecated: .toggleClass() with no arguments and .toggleClass( Boolean )

引数無しのtoggleClass()はDeprecatedだよ。
あと、これまで.toggleClass(false)という指定があったけど、未定義の動作だったので廃止したよ。
これも引数無しと同じ動作になるよ。

## Callbacks

### Feature: Locking a Callback prevents only future list execution

.fire()後に.lock()した場合、次回以降の.fire()は止まるけど現在実行中のコールバックは止まらないよ。
現在実行中のも止めたい場合はstopOnFalseオプションを使おう。

## Core

### Breaking change: jQuery 3.0 runs in Strict Mode

jQueryは`"use strict"`で動くようになったよ。
あなたのコードはStrict Modeで動作してもしなくてもいいよ。
前は古いASP.NETのせいで[arguments.caller.callee](http://masahito.hatenablog.com/entry/20111125/1322208619)を使わざるを得なかったけど、最近のブラウザはerror.stackがあるからStrictにできたよ。
未だにASP.NETなんぞ使ってる場合はjQuery2を使ってね。

### Breaking change: document-ready handlers are now asynchronous

Document.readyが非同期になったよ。

```js
$(function(){
   console.log("ready");
});
console.log("outside ready");
```

以前はどっちが先に動くかわからなかったけど、jQuery3では必ず先に"outside ready"が動くよ。
Document.readyを複数書いた場合、これまでは一つがこけると他も共倒れになってたけど、3.0では独立して動くよ。

### Breaking change: jQuery.isNumeric() and custom .toString()

`$.isNumeric()`は.toString()を見なくなったよ。
これまではtoString()が数値だったらtrueだったけどjQuery3ではfalseだよ。

### Breaking change: Deprecated .context and .selector properties removed

jQuery1.9でdeprecatedになってた.contextと.selectorプロパティを削除したよ。

### Breaking change: Undocumented internal methods no longer exposed

privateのつもりで作ってたのでドキュメント化してなかった3メソッドを削除したよ。
`$.swap()、$.buildFragment()、$.domManip()`。

### Breaking change: Return values on empty sets are undefined

これまでnullを返していた一部メソッドは、[ガイドライン](https://github.com/jquery/jquery/wiki/API-design-guidelines)に従ってundefinedを返すようにしたよ。
.width()、.height()、.innerWidth()、.innerHeight()、.outerWidth()、.outerHeight()、.offsetTop()、.offsetLeft()。
ただし一部例外を除く。上記のselect-multipleとか。

### Feature: for...of loops can be used on jQuery collections

jQueryのコレクションに対してES2015のfor-ofが使えるようになるよ。

```js
	var elems = $(".someclass");

	// これまで
	$.each(elems, function(i, elem) {
		// upgrade-guideのここ間違ってる
	});

	// ES2015
	for ( let elem of elems ) {
		// const[name, value]形式は使えないみたい？
	}
```

### Feature: jQuery.ready promise is formally supported

`$.ready`のpromiseに正式対応したよ。

```js
	$.when( $.ready, $.getScript("optional.js") ).then(function() {
	   // 両方が成功
	}).catch( function() {
	   // どっちかが失敗
	});
```

### Deprecated: jQuery.unique(), renamed to jQuery.uniqueSort()

.unique()は名前がおかしかったからuniqueSort()に変更したよ。
といってもソート順はあくまでDOM順で、[2,1,2,1]は[2,1]になるだけで[1,2]にはならないので正直わかりにくい。

### Deprecated: jQuery.parseJSON()

jQuery3が対応してる全ブラウザがJSON.parse()に対応したから$.parseJSON()は削除したよ。

### Deprecated: document-ready handlers other than jQuery(function)

jQueryの呼び出し方は歴史的事情で色々あるけど、`$(fn);`以外はDeprecatedだよ。
`$(document).on("ready", fn)`は削除したよ。

## Data

### Breaking change: .data() names containing dashes

data属性名に-が入ってるときの挙動が変更になったよ。

```js
<div id="x" data-a="aa" data-b-b="bb" />
$(document).ready(function(){
	console.log($("#x").data("a"));   // aa
	console.log($("#x").data("b-b")); // bb
	console.log($("#x").data("bB"));  // bb
	console.log($("#x").data("b-B")); // undefined 2.2ではbb
	console.log($("#x").data("bb"));  // undefined
});
```

そもそも書き方を半端に混ぜるなって話だな。

## Deferred

### Breaking change and Feature: jQuery.Deferred is now Promises/A+ compatible

`$.Deferred`が[Promises/A+](https://github.com/promises-aplus/promises-spec)互換になったよ。

```js
	// 新記法
	$.ajax("/status")
	    .then(function(data) {
	        // 成功した
	        // ここで例外投げるとcatchに捕捉される
	    })
	    .catch(function(arg) {
	        // 失敗した
	    });

	// 昔の書き方
	$.ajax("/status")
	    .done(function(data) {
	        // 成功した
	        // ここで例外投げると死ぬ
	        // .done(function( data, textStatus, jqXHR )
	    })
	    .fail(function(arg) {
	        // 失敗した
	        // .fail(function( jqXHR, textStatus, errorThrown )
	    });
```

例外が出たらjQueryログが出力されるので、出したくない場合はjQuery.Deferred.exceptionHookにundefinedを設定すればいいよ。
あとthenは引数がひとつしかないから、textStatusやjqXHRが必要なら以前の書き方をしないといけないみたい。

### Breaking change and Feature: jQuery.when() arguments

`$.when`は[Promise](https://promisesaplus.com/#point-7)とBluebirdに互換するthenableとして動作するよ。
引数が複数あったらPromise.allとして、引数が1個か0の場合はPromise.resolveとして動作するよ。
個人的には引数によって動作が変わるメソッドって好きではないので別名にしてほしいんだけど、jQueryは(JavaScriptは?)そういうの大好きだから仕方ないね。
あとBluebirdってのは[これ](http://qiita.com/kamijin_fanta/items/21a061a00575f0a357c6)のことでいいんだろか。

### Breaking change: jQuery.when() progress notifications

`$.when()`は進捗状況を通知しないよ。
みたいなことが書いてあるみたいなんだけどそもそも今までwhenに通知機能ってあったの？

## Dimensions

### Breaking change: .width(), .height(), .css("width"), and .css("height") can return non-integer values

これまでintegerしか返さなかったけど、今後は数値以外が返ってくるかもしれないよ。小数とか。
というか.css("width")したら"100px"って文字列が返ってきた。

### Breaking change: .outerWidth() or .outerHeight() on window includes scrollbar width/height

width()はスクロールバーが入ってない状態の幅だけど、CSSのwidthはスクロールバーを含めた幅で、異なってるから使いにくいよ。
なのでouterWidth()はスクロールバーを含めた幅を返すようにしたよ。
こいつはDOMのwindow.innerWidthと同じだよ。

## Effects

### Breaking change: .show(), .hide(), and .toggle() methods now respect more stylesheet changes

`show()/hide()`はCSSを尊重するようにしたよ。
最初から表示されてるものをhide()してshow()はできるけど、CSSにdisplay:noneって書いてあるものはshow()できなくなるよ。

みたいなことが書いてあって、実際α版のころは出ないようになってたみたいなんだけど、RCでは何故か再び動くようになってる。
http://qiita.com/fmy/items/abdeeb9abaf56058c20e
http://bashalog.c-brains.jp/15/07/17-214854.php
https://jsfiddle.net/23u8sjz7/
何があったのだろう。

### Feature: Animations now use requestAnimationFrame

アニメーションはrequestAnimationFrameを使うようになったよ。
IE9以外な！

### Deprecated: Additional easing function parameters

`$.easing`は引数をひとつしか持てなくなるよ。

## Event

### Breaking change: .load(), .unload(), and .error() removed

`load()、unload()、error()`は削除されたよ。
`.on("load", fn)`みたいにonに入れ替えてね。

### Breaking change: .on("ready", fn) removed

.onの中でも`.on("ready", fn)`は廃止されたよ。
`$(fn)`って書くといいよ。

### Breaking change: event.pageX and event.pageY normalization removed

`event.pageX/pageY`の正規化が削除されたよ。
おそらく古いIE用の補正のことかと思われる。

### Breaking change: jQuery.event.props and jQuery.event.fixHooks removed

`$.event.props`と`$.event.fixHooks`を削除したよ。
まだ必要な場合は移行プラグイン使うといいよ。

### Breaking change: Delegated events with bad selectors throw immediately

無効なセレクタは、これまでは使用したときに初めてチェックしていたけど、jQuery3ではセレクトした時点でチェックするよ。

### Deprecated: .bind() and .delegate()

5年前のjQuery1.7で`.on()`作ったんだから、いいかげん`bind()/unbind()/delegate()/undelegate()`は削除しようや。

## Manipulation

### Breaking change:  .wrapAll(function) only calls the function once

`wrapAll()`に関数を渡した場合`wrap()`と同じ動作になってたけど、jQuery3では正しく動作するようにしたよ。

## Offset

### Breaking change: Invalid input to the .offset() method

`offset()`に渡す引数は、getBoundingClientRect()を持ってるオブジェクトじゃないといけないよ。
jQuery3対応ブラウザは全部対応してるから問題ないよ。

## Selector

### Breaking change: Behavior of :hidden and :visible

高さや幅が0だったとしても、getClientRects()メソッドがあれば:visibleと判定するよ。
`<br /><span />`みたいな中身がないから描画されない要素はvisibleだよ。

### Breaking change: jQuery("#") and .find("#") are invalid syntax

`$("#")`と`.find("#")`が構文エラーを出すようにしたよ。
前は`$("#")`は空のコレクション、`.find("#")`はただのJavaScriptのエラーだったよ。

### Feature: New method jQuery.escapeSelector()

`$.escapeSelector()`はセレクタ文字列をエスケープするよ。
例えば`$("#abc.def")`って書いたら`id="abc" class="def"`って解釈されちゃうけど、`$("#"+$.escapeSelector("abc.def"))`って書けば`id="abc.def"`を探せるようになるよ。
尤も、その前に変な名前を付けないようにした方がいいと思うが。

### Deprecated: jQuery.expr[":"] and jQuery.expr.filters

このふたつはjQuery.expr.pseudosと同じだからDeprecatedにしたよ。

## Serialize

### Breaking change: jQuery.param() no longer converts %20 to a plus sign

`$.param()`はスペースを+に変換しないよ。
この機能は`application/x-www-form-urlencoded`の仕様だから`$.ajax()`に移されたよ。
`$.param()`はencodeURIComponentを使うから、スペースを%20に変換するよ。

# 感想

そもそも変更前の仕様を知らないところが多かった。
英語もJavaScriptもうろ覚えなのに英語のJavaScriptの文章を読もうとか思ってはいけない。