2017/10/22

JavaScriptのin演算子はいつ使う?テストでしょ

JavaScript 


in演算子、使ってますか? 普通はfor文で使いますよね。

最近、JavaScript玄人に「テストで使うべき!」と教えてもらったので、みなさんにも紹介しますね。




for in の使い方

これはよくある使い方です。


オブジェクトや配列を繰り返して処理することができます。


var hoge = ['piyo1', 'piyo2'];
for (var piyo in hoge) {
    console.log(piyo);
}

実行結果は次の通りです。

// 添え字が返却されます。
0
1

今回はfor文のお話ではないので、サクッと割愛しますね。


in演算子の使い方

さてここからが本題です。


in演算子はオブジェクトや配列について指定したプロパティが存在するかチェックするためのものです。


と言われてもなんだかな、という感じなので実際にコードを見てみましょう。


// 配列の場合
var hoge = ['piyo1', 'piyo2'];

console.log(0 in hoge);			// true
console.log(1 in hoge);			// true
console.log(2 in hoge);			// false
console.log('length' in hoge);		// true
console.log('lengthpiyo' in hoge);	// false

配列の場合は添字とArrayが持つプロパティが存在するかチェックできます。

つまり、Arrayかどうかチェックすることができるのです。

'length' inはなかなか使えるのではないでしょうか。


// オブジェクトの場合
var hoge = {
    piyo: 'piyo1',
    fuga: 'fuga1'
};
console.log(0 in hoge);			// false
console.log('piyo' in hoge);		// true
console.log('piyo1' in hoge);		// false
console.log('length' in hoge);		// false
console.log('toString' in hoge);		// true

また、オブジェクトの場合は定義したプロパティとObjectが持つプロパティが存在するかチェックできます。

オブジェクトかどうかチェックすることができますが、そういう使い方は実際にはあまり使わないですけどね。

typeofinstanceofで事足りますので。


ではどういう使い方がより良いのでしょう。

次の章で紹介します。



テストコードでin演算子の本領発揮!

突然ですが、JavaScriptの単体テストコードを書いてますか?

書いてない人は早速書きましょう!

そしてin演算子の素晴らしさを体験してください。


インターフェース定義のテスト

JavaScriptにはちゃんとしたクラス定義がありません。

クラスを作ってもただのオブジェクトですので、まったく違うメンバー変数でもセットできてしまいます。

他言語でいうところの連想配列やMapみたいな感じです。

そこで役に立つのがin演算子です。


インターフェース定義のテストができてしまいます。


サンプルコードは次の通りです。


// クラス定義
class Hoge {
    piyo: string,
    fuga: number
};
// メソッドからHogeクラスのデータを取得する
var hoge = getHoge();

// プロパティ存在チェック
expect('piyo' in hoge).toBeTruthy();
expect('fuga' in hoge).toBeTruthy();
// 型チェック
expect(hoge.piyo).toEqual(jasmine.any(String));
expect(hoge.fuga).toEqual(jasmine.any(Number));

いかがでしょうか。

関数レベルでの結合テストを行うテストコードを書いてみました。


少しアレンジすると、APIの戻り値もテストが可能です。

APIの場合は特にインターフェースの取り決めが重要になりますので、定義はしっかりとテストしなければなりません。


おまけ。ちょっとモダンな存在チェック

まぁ、個人的にはinでも十分だと思っていますけども。


Arrayかどうかチェックする

Array.isArrar()を使います。

※古いIEは動きませんので注意


// Array.isArrar()の実行結果
console.log(Array.isArray(null));		// false
console.log(Array.isArray(undefined));	// false
console.log(Array.isArray(1));			// false
console.log(Array.isArray('piyo'));		// false
console.log(Array.isArray({}));			// false
console.log(Array.isArray([]));			// true
console.log(Array.isArray(['piyo']));		// true

オブジェクトにプロパティがあるかチェックする

Object.hasOwnProperty()を使います

in演算子との違いは、2つあります。

  • 初めからObjectと分かっている前提の処理
  • prototypeチェーンをさかのぼらない

// Object.hasOwnProperty()の実行結果。inとの違い
function Hoge() {
  this.hoge = 'hoge';
}
function Piyo() {
  this.piyo = 'piyo';
}
Hoge.prototype = new Piyo();
Piyo.prototype.fuga = 'fuga';

var obj = new Hoge();

// Object.hasOwnProperty() の場合、prototypeチェーンをさかのぼらない
console.log(obj.hasOwnProperty('hoge'));		// true
console.log(obj.hasOwnProperty('piyo'));		// false
console.log(obj.hasOwnProperty('fuga'));		// false
// in の場合、prototypeチェーンをさかのぼる
console.log('hoge' in obj);					// true
console.log('piyo' in obj);					// true
console.log('fuga' in obj);					// true

私はin演算子のほうが理解しやすいと思うので、そちらをおススメしています。


まとめ

  • in演算子は添字やプロパティが存在するかチェックできる
  • インターフェース定義のテストで使おう

いかがでしたか。


みなさんも、JavaScriptの自動化テストでin演算子を利用して、良きテストライフを送ってくださいね。



このエントリーをはてなブックマークに追加