is.javascript()？

多種多様な「YesかNoか」判定を簡単に行える[is.js](http://is.js.org/)を紹介するぞ。
なんと100以上の"is"が入っててわずか13KBだ。
確認したバージョンは0.8.0。

# 使用方法

`npm install is_js --save`

npmのインストールなどは[このあたり](http://qiita.com/taipon_rock/items/9001ae194571feb63a5e)を参照のこと。

# メソッド

特徴として、文法的に正しいかぎり、何を突っ込もうが必ずtrue|falseどちらかが返ってくる。
以下の例示は注釈のないかぎり返り値はtrue。

## 型

```javascript
	
	// argumentsオブジェクトである
	is.arguments( function(){return arguments;}() );
	
	// 配列である
	is.array([1,2]);
	
	// bool値である
	is.boolean(false);
	
	// Dateオブジェクトである
	is.date(new Date());
	is.date(new Error()); // false
	
	// Errorオブジェクトである
	is.error(new Error());
	is.error(new Date()); // false
	
	// functionである
	is.function(function(){});
	
	// NaNである
	is.nan(NaN);
	
	// nullである
	is.null(null);
	is.null(undefined); // false
	
	// 数値である
	is.number(1);
	is.number(Number('1'));
	
	// Objectである
	is.object({});
	is.object(new Date());
	
	// JSONオブジェクトである
	is.json({});
	is.json(new Date()); // false
	
	// 正規表現リテラルである
	is.regexp(/reg/);
	is.regexp('/reg/'); // false
	
	// Stringリテラルである
	is.string('/reg/');
	is.string(/reg/); // false
	
	// Charである
	is.char('a'); // is.stringかつlength=1
	
	// undefinedである
	is.undefined(undefined);
	
	// 2引数が同じ型である
	is.sameType(1, 10);
	is.sameType({},[]); // false
```

簡単に厳密な型チェックができる。

## 存在チェック

```javascript

	// 空っぽい
	is.empty({});
	is.empty('');
	
	// 存在する
	is.existy({});
	is.existy('');
	
	// trueっぽい
	is.truthy({});
	is.truthy('1');
	
	// falseっぽい
	is.falsy(0);
	is.falsy('');
	
	// スペース1文字だけ
	is.space(' ');
	is.space("\t");
	is.space('  '); // 2文字はfalse
	is.space('　'); // 全角はfalse
```

こちらは比較的アバウトな比較。
`is.space`は"\v"、"\r"、"\n"、"\f"に対してもtrue。"\b"は対象外。

## 正規表現

```javascript
	// URLである
	is.url('http://www.example.com');
	is.url('p.m.ls'); // true
	is.url('p.m.l.s'); // false
	
	// メールアドレスである
	is.email('a.b@c.d');
	is.email('a..b@c.d'); // false
	
	// 16進数である
	is.hexadecimal('abcdef');
	
	// CSSカラーコード形式である
	is.hexColor('#ff0000');
	is.hexColor('#f00');
	is.hexColor('red'); // false
	
	// IPアドレスである
	is.ip('192.168.0.1');
	is.ip('fc00::1');
	
	// IPv4アドレスである
	is.ipv4('192.168.0.1'); // true
	is.ipv4('fc00::1'); // false
	
	// IPv6アドレスである
	is.ipv6('192.168.0.1'); // false
	is.ipv6('fc00::1'); // true
	
	// 英数
	is.alphaNumeric('alphaNu3er1k');
	is.alphaNumeric('a_b'); // false
	
	// 時刻
	is.timeString('12:34:56')
	is.timeString('1:2:3')
	is.timeString('12:34:60') // false
	
	// 年月日
	is.dateString('01/01/2017'); // 区切りは/-いずれか
	is.dateString('2017/01/01'); // false
	
	// 肯定的である
	is.affirmative('yes');
	is.affirmative('no'); // false
	
	// クレジットカード
	is.creditCard(378282246310005)
	
	// アメリカの郵便番号
	is.usZipCode('12345-6789'); // true
	is.usZipCode('100-0001'); // false
	
	// カナダの郵便番号
	is.caPostalCode('L8V3Y1'); // true
	is.caPostalCode('100-0001'); // false
	
	// イギリスの郵便番号
	is.ukPostCode('B184BJ'); // true
	is.ukPostCode('100-0001'); // false
	
	// 北米の電話番号
	is.nanpPhone('609-555-0175'); // true
	
	// アメリカの社会保障番号
	is.socialSecurityNumber('017-90-7890'); // true
	
	// EPP（Extensible Provisioning Protocol)
	is.eppPhone('+90.2322456789'); // true
```

わりとざっくり。
日本ではちょっと使えないものが多いというか、ライブラリに入れるようなものなのかこれ。
`is.affirmative`は1、't'、'true'、'y'、'yes'、'ok'、'okay'だけがtrueになるようだ。`affirmative`自身もfalse。

## 文字列

```javascript
	
	// 文字が含まれるか
	is.include('I am a Cat', 'I am'); // true
	is.include('I am a Cat', 'i am'); // false
	
	// 文字で始まるか
	is.startWith('I am a Cat', 'I am'); // true
	is.startWith('I am a Cat', 'a Cat'); // false
	
	// 文字で終わるか
	is.endWith('I am a Cat', 'I am'); // false
	is.endWith('I am a Cat', 'a Cat'); // true
	
	// 単語が大文字開始か
	is.capitalized('I am a Cat') // false
	is.capitalized('I Am A Cat') // true
	
	// 全て大文字か
	is.upperCase('AAA'); // true
	is.upperCase('AaA'); // false
	
	// 全て小文字か
	is.lowerCase('aaa'); // true
	is.lowerCase('aAa'); // false
	
	// 回文か
	is.palindrome('Sator Arepo Tenet Opera Rotas.'); // true [a-zA-Z0-9]以外は全削除される
	is.palindrome('竹藪焼けた'); // true 日本語も削除対象なので正しく動かない
```

`is.palindrome`以外は日本語も動作するが、日本語は大文字とかないので`is.upperCase`等は常にtrueになる。
`つ`が`っ`になったりはしない。

## 算術

```javascript
	
	// 同じである
	is.equal(40+2, 42); // true
	is.equal(a=new Date(), b=a) // string、number、boolean以外はfalse
	
	// 偶数である
	is.even(2);
	
	// 奇数である
	is.odd(1);
	
	// 0より大きい
	is.positive(1);
	is.positive('1'); // false
	
	// 0未満である
	is.negative(-1);
	is.negative(0); // false
	
	// より大きい
	is.above(2, 1); // 第二引数より大きければtrue
	is.above(2, 2); // 同値はfalse
	
	// より小さい
	is.under(2, 3); // 第二引数より小さければtrue
	is.under(2, 2); // false
	
	// 値が間にあるか
	is.within(2, 1, 3); // 第二引数より大きく第三引数より小さければtrue
	is.within(2, 2, 2); // false
	
	// 小数である
	is.decimal(1.1);
	is.decimal(1.0); // false
	
	// 整数である
	is.integer(1);
	is.integer(1.1); // false
	is.integer(1.0); // true
	
	// 有限である
	is.finite(1);
	is.finite(Infinity); // false
	
	// 無限である
	is.infinite(Infinity);
	is.infinite(1); // false
```

`1.0`は`1`に丸め込まれるようだ。

## オブジェクト

```javascript
	
	// プロパティ数
	is.propertyCount({a:0,b:0}, 2);
	
	// プロパティ名が存在するか
	is.propertyDefined({a:'b'}, 'a');
	is.propertyDefined({a:'b'}, 'b'); // false
```

`propertyDefined`は`property_exists()`。

## 配列

```javascript

	// in_array()
	is.inArray(1, [1, 2]);
	is.inArray(1, {a: 1}); // false
	
	// ソートされているか
	is.sorted([1, 2, 3]); // デフォルト第二引数は`>=`
	is.sorted([1, 3, 2]); // false
	is.sorted([3, 2, 1], '<'); // true
```

何故inArrayだけ引数が逆順なのか。

## 環境

```javascript
	
	// IEか
	is.ie();
	is.ie(10); // IE10か
	is.ie('>=10'); // IE10以上か
	
	// Chromeか
	is.chrome();
	
	// Firefoxか
	is.firefox();
	
	// Edgeか
	is.edge();
	
	// Operaか
	is.opera();
	
	// safariか
	is.safari();
	
	// phantomjsか
	is.phantom()
	
	// iosか
	is.ios();
	
	// iPhoneか
	is.iphone();
	
	// iPadか
	is.ipad();
	
	// iPodか
	is.ipod();
	
	// Androidか
	is.android();
	
	// Androidスマホか
	is.androidPhone();
	
	// Androidタブレットか
	is.androidTablet();
	
	// Blackberryか
	is.blackberry();
	
	// Windows Phoneか
	is.windowsPhone();
	
	// Windowsタブレットか
	is.windowsTablet();
	
	// Windowsか
	is.windows();
	
	// Mac OS Xか
	is.mac();
	
	// Linuxか
	is.linux();
	
	// デスクトップPCか
	is.desktop();
	
	// 携帯端末か
	is.mobile();
	
	// タブレットか
	is.tablet();
	
	// 現在オンラインか
	is.online(); // navigator.onLine
	
	// 現在オフラインか
	is.offline(); // 何故かCannot read property 'apply' of undefinedになる
	
	// タッチ可能なデバイスか
	is.touchDevice();
```

`is.ie`以外にも`is.chrome`や`is.firefox`あたりはバージョン指定で検索可能。

## 時刻

```javascript
	
	var today = new Date();
	var yesterday = new Date(new Date().setDate((today.getDate())-1));
	var tomorrow  = new Date(new Date().setDate((today.getDate())+1));
	var millennium = new Date('2001/01/01 00:00:00');
	
	// 今日か
	is.today(today);
	is.today(yesterday); // false
	is.today(); // false！
	
	// 昨日か
	is.yesterday(yesterday); // true
	is.yesterday(today); // false
	
	// 明日か
	is.tomorrow(tomorrow); // true
	is.tomorrow(today); // false
	
	// 過去か
	is.past(yesterday); // true
	is.past(today); // false
	
	// 未来か
	is.future(tomorrow); // true
	is.future(today); // false
	
	// その曜日か
	is.day(millennium, 'monday'); // 2001/01/01は月曜
	is.day(millennium, 'sunday'); // false
	
	// その月か
	is.month(millennium, 'january');
	is.month(millennium, 'february'); // false
	
	// その年か
	is.year(millennium, 2001);
	is.year(millennium, '2001'); // false
	
	// 閏年か
	is.leapYear(2000); // true
	is.leapYear(new Date('2000/01/01 00:00:00')); // false！
	
	// 週末か
	is.weekend(new Date('2001/01/06 00:00:00')); // 土日がtrue
	is.weekend(millennium); // false
	
	// 平日か
	is.weekday(millennium); // true
	is.weekday(new Date('2001/01/06 00:00:00')); // 土日がfalse
	
	// 日付が間にあるか
	is.inDateRange(today, yesterday, tomorrow); // 第二引数より大きく第三引数より小さければtrue
	is.inDateRange(millennium, yesterday, tomorrow); // false
	
	// 過去一週間以内か
	is.inLastWeek(yesterday); // '先週'ではない
	is.inLastWeek(today); // false
	
	// 過去一ヶ月以内か
	is.inLastMonth(yesterday); // '先月'ではない
	is.inLastMonth(new Date(new Date().setMonth((today.getMonth())-1))); // false
	
	// 過去一年以内か
	is.inLastYear(yesterday); // '昨年'ではない
	is.inLastYear(new Date(new Date().setYear((today.getYear())-1))); // false
	
	// この先一週間以内か
	is.inNextWeek(tomorrow); // '来週'ではない
	is.inNextWeek(today); // false
	
	// この先一ヶ月以内か
	is.inNextMonth(tomorrow); // '来月'ではない
	is.inNextMonth(new Date(new Date().setMonth((today.getMonth())+1))); // false
	
	// この先一年以内か
	is.inNextYear(tomorrow); // '来年'ではない
	is.inNextYear(new Date(new Date().setYear((today.getYear())+1))); // false
	
	// 指定の四半期か
	is.quarterOfYear(millennium, 1); // true 1月スタート
	is.quarterOfYear(millennium, 2); // false
	
	// 夏時間か
	is.dayLightSavingTime(new Date('2001/06/01 00:00:00')); // 日本では常にfalse
```

便利ではあるが、JavaScriptは[Dateの存在自体が罠](http://qiita.com/labocho/items/5fbaa0491b67221419b4)なのであまり積極的に使いたいものではない。

## 設定


```javascript
	
	// 正規表現変更
	is.setRegexp(/^\d+$/, 'alphaNumeric'); // is.alphaNumericをA-Za-z0-9から0-9に変更
	is.alphaNumeric('123'); // true
	is.alphaNumeric('abc'); // false
	
	is.setRegexp(/^[\u3040-\u30ff]+$/, 'zenkaku'); // これは動かない
	is.zenkaku('ほげ'); // JavaScriptエラー
	
	// 名前変更
	var hoge = is.setNamespace();
	hoge.boolean(false); // isの名前が変わる
	is.boolean(false); // JavaScriptエラー is=undefinedになる
	
```

設定変更系の特殊なメソッド。
`is.setRegexp`は任意の名前をセットできるかと思いきや、既存の正規表現を変更することしかできないというがっかり仕様。


# 派生メソッド

ここまでに挙げた「設定」以外の全`is.**`メソッドに対して、`is.not.**`でnot検索ができる。

```javascript
	
	is.not.boolean(1); // true
	is.not.boolean(false); // false
	
	is.not.within(2, 2, 2); // 範囲内はない
	
	is.not.ie(); // IE以外である
	
	is.not.online(); // is.offline()と同じ
	
	is.not.past(today); // 過去ではない
```

「環境」「設定」以外の、引数がひとつのメソッドでは、`is.any.**`で複数渡したパラメータのうち少なくとも一つが対象であるかを、`is.all.**`で引数全てが対象であるかをチェックできる。


```javascript
	is.all.number(1, 2, 3); // true
	is.all.number(1, 2, null); // false
	is.any.number(1, 2, null); // true
	is.any.number('1', undefined, null); // false
```

さすがに`is.not.all.number`とかは書けない。
`is.inNextYear`あたりはヘルプでは[all、any非対応](https://github.com/arasatasaygin/is.js#isinnextyearvaluedate)になっているけど、普通に対応してる。


# 感想

○○かそうでないかを確かめたい、をとにかく詰め込んだライブラリ。
色々と範囲がばらばらで、一見まとまりがないようにも見えるけど、実際あったら便利なものが多い。
もうnull==undefinedの罠に怯える必要はないぞ。