配列とarguments
引き続き「テスト駆動JavaScript」本を読んで勉強しているのですが、ちょっと混乱した箇所があったのでメモ。
「第11章 Observerパターン」の「11.4.2 引数を渡す」の項目で以下のコードがテストを合格すると記述されていたのですが……
テストコード(リスト 11-24 notifyObservers に渡された引数が観測者に渡されることを確かめる)
1 2 3 4 5 6 7 8 9 10 11 12 |
"test should pass through arguments":function(){ var observable = new tddjs.util.Observable(); var actual; observable.addObserver(function(){ actual = arguments; }); observable.notifyObservers("String", 1, 32); assertEquals(["String", 1, 32], actual); } |
実装 (リスト 11-25 applyを使ってnotifyObservers に渡された引数を渡す)
1 2 3 4 5 |
function notifyObservers(){ for(var i=0, l=this.observers.length; i< l; i++){ this.observers[i].apply(this, arguments); } } |
これだと、使用するテストフレームワークによっては合格しません。
例えばYUIのテストフレームワークでは失敗します。(※1)
argumentsは配列(Array)に似たオブジェクトですが、配列では無いので上記のテストが合格してしまうのは微妙な感じです。
もし、このテストを合格させるのであれば、argumentsを配列に変換する必要があるんじゃないかと思います。
addObserveでactualに引数を配列に変換しておさめる
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
"test should pass through arguments":function(){ var observable = new tddjs.util.Observable(); var actual=[]; observable.addObserver(function(){ actual = Array.prototype.slice.call(arguments); }); observable.notifyObservers("String", 1, 32); assertEquals(["String", 1, 32], actual); } |
YUIのAssert.areEqualでは配列を比較すると「参照元が同じかどうか」をみているので失敗します。
YUIのAssert.areEqual – jsdo.it – share JavaScript, HTML5 and CSS
1 |
Assert.areEqual(["String", 1, 32], ["String", 1, 32]); //FAILになる |
上記が失敗するのは、それはそれで微妙な感じ。