先日、Visual Studio 2015のTypeScriptでこんなミスをした。
分かってみると単純な間違いなのだが、その原因を特定するまでに1時間くらい掛かってしまった。
まあ、結論としてはワテのウッカリミスなのだが、JavaScript/TypeScriptをやっていてこんな失敗をしたのは初めてだ。
その状況
ASP.NET MVCのプロジェクトに於いて、 .cshtml ファイルの中でオブジェクトを作成してそれを localStorage に保存した。
var userid = '12345'; var userName = 'Wate'; localStorage.setItem('data_usr', JSON.stringify( { 'userid': userid, 'userName ': userName } ) );
今の場合は ASP.NET MVCと言うマイクロソフト社固有の技術だが、今回の問題の本質はそれとは無関係で、普通のJavaScriptやTypeScriptでも起こり得る。
さて、そのローカルストレージに保管したデータを後で読み出した。
その部分のコードは以下の通り。
var strJson = localStorage.getItem('data_usr'); var dataObj = JSON.parse(strJson); var userid = dataObj['userid']; var userName = dataObj['userName']; // 何故か undefinedになる
ごく普通の処理だと思う。
でも何故か、userName の値が undefined なのだ。
不思議な事に、useridの値は正しく取得出来る。
じゃあ、オブジェクトから値を取り出す場合のKey指定を角カッコ[]を使うのではなくて、ドットを使う方式してみた。
var userName = dataObj.userName; // 何故か undefinedになる
う~ん、おかしい。
デバッガーでブレークして中身を確認しても undefined だ。
じゃあ、オブジェクトの中味を全部表示させてみる。
for (var key in dataOb) { var value = dataObj[key]; alert('key= ->' + key+ '<-, value= ->' + value + '<-'); }
そしたら、ちゃんと
'key= ->userid<- , value= ->12345<-' 'key= ->userName <-, value= ->Wate<-'
と表示されるがな。
益々分からん??
どういう事?
狐につままれるとはこの事か。
Visual Studio のJavaScriptにバグがあるのか?
絶対にそうに違いない。
と思うくらい、不思議な挙動だ。
何でかな?
分からん。
そんなこんなで1時間くらい経ってしまった。
その理由の一つは、上記のlocalStorageの方法を用いてやっていたのは、WEBページを遷移した場合に、各ページ間でデータを受け渡ししたかったのでこんな手法を用いたのだが、そういうページを切り替える場合にVisual StudioのTypeScriptのデバッガの操作がややこしかったので。
慣れてしまうと問題は無いのだが。
解決
まあ、勘の良い皆さんなら既にお気付きだとは思うが、ワテの場合にも
'key= ->userName <-, value= ->Wate<-'
このメッセージを見て気づいた。
半角スペースが入っているぞ!?
ああ、そう言う事か!!
JavaScriptのオブジェクトを作成する時に、Keyになる文字列にウッカリ半角スペースを入れてしまった。
{ 'userid': userid, 'userName ': userName }
それが原因だった。
半角スペースが入る事自体は文法的には問題は無いのだが、逆にオブジェクトから値を取り出す操作に於いても、半角スペースを入れて
var userName = dataObj['userName '];
とすれば良い。
あるいは、setする時の半角スペースを除去すれば解決する。まあそうだな。
まとめ
JavaScript/TypeScriptにおいてオブジェクトを操作する処理に於いては、ウッカリとKeyの前後に半角空白を入れてしまうとワテのような失敗をする事になるので要注意だ。
ちなみに、ワテの場合には文字列を出力する場合にはその前後に記号を入れて
->文字列<-
こんなふうに出すようにしている。具体的にはこんな感じ。
alert( 'key= ->' + key+ '<- );
JavaScriptだけでなく、C, C++, C# でもやっている。文字列の前後に予想外の空白や改行文字が入っている場合でも、こうしておくと気付き易いからだ。
今回のウッカリミスもこの方式のおかげで気づいた。
皆さんにもお勧めしたい。
なおここで用いたローカルストレージは便利なので皆さんにもお勧めしたい。
localStorage.setItem( key, strData );
や
var strData = localStorage.getItem( key );
を利用すると、ローカルパソコンに手軽にデータを保存出来る。
何らかのデータの一時保管、ページ間でのデータの受け渡し、Cookie(クッキー)の代わりに使える。
保存出来るのは文字列なのでもしオブジェクトデータを保存したい場合にはJSON.stringify() で文字列化する。逆変換はJSON.parse()でオブジェクトを生成出来る。
バイナリデータを保存したい場合にはどうするのかな?
まあBase64文字列にでも変換してやれば保管出来るなあ。
なお、HTML5の仕様では、ローカルストレージ容量は大体5MBくらいのようなので、あまり巨大なデータを保存する場合には何らかの別の手法が必要になる。
その辺りの手法は引き続き調査したい。
コメント