Chromeのconsole.logの謎
この記事を読んで、Chromeのconsole.logの動きが謎すぎる気がして確認してみました。
CoffeeScriptで、newするときのプロパティ変数の初期化ってどーなってんの? - uzullaがブログ
検証
ソースコード
var a = []; a.push('A'); console.log(a); a.push('A'); console.log(a);
これをChromeのDeveloper toolのコンソールで実行してみました。
期待する出力
["A"] ["A", "A"]
実際の出力
["A", "A"] ["A", "A"]
調べてみた
console.log lazy等でググるとStackoverflow等のサイトがでてきた。
Is Chrome's JavaScript console lazy about evaluating arrays? - Stack Overflow
javascript - Bizarre console.log behaviour in Chrome Developer Tools - Stack Overflow
35801 – Web Inspector: generate preview for the objects dumped into the console upon logging.
なるほど。Webkit特有なのかもしれません。
console.logにオブジェクトを渡すと、console.logはそのオブジェクトの内容を出力します。
console.logが出力する準備をしている間にそのオブジェクトに変更を加えると変更後のオブジェクトの内容が出力されると。
シンプルな解決方法として
- JSON.stringify
- toString
- slice (配列の場合)
等のメソッドや関数を使って別のオブジェクトを作成してから渡す方法が挙げられてますね。
ちなみに
Coffeescriptのクラスのプロパティ変数って、初期化が必須なの?(;´Д`) コンストラクタで宣言しなおさないと、暗黙のウチに共有されちゃうの? そういうもんなの??
JavaScriptのprototype継承ですね。
class Chain queue: [] test: -> @queue.push "A"
は
var Chain; Chain = (function() { function Chain() {} Chain.prototype.queue = []; Chain.prototype.test = function() { return this.queue.push("A"); }; return Chain; })();
JavaScriptになるとこうなっています。
Chainクラスはprototypeというオブジェクトを持っています。(以下prototypeオブジェクト)
CoffeeScriptのクラスのメソッド等はこのprototypeオブジェクトのプロパティに定義されます。
Chainクラスのインスタンスはprototypeオブジェクトへの参照を持っています。
Chainクラスのインスタンスからqueueプロパティにアクセスするとき
- まずインスタンス自身がqueueプロパティを持っていないか調べる
- 持っていなければクラスのprototypeオブジェクトにqueueがないか調べる。
- クラスのprototypeオブジェクトにもqueueプロパティがなければ更に継承元のクラスを辿って行く
という感じになってます。
インスタンス自身がプロパティを持っているかどうか調べるためにはhasOwnPropertyを使います。
例
class Chain queue: [] test: -> @queue.push "A" c = new Chain console.log "before c.queue = []" console.log c.hasOwnProperty "queue" c.queue = [] console.log "after c.queue = []" console.log c.hasOwnProperty "queue"
こう書くとなおるわけ
例
class Chain constructor: -> @queue = [] console.log "c = new Chain" c = new Chain console.log "c.hasOwnProperty 'queue': #{c.hasOwnProperty 'queue'}"
JavaScriptになると
var Chain, c; Chain = (function() { function Chain() { this.queue = []; } return Chain; })(); console.log("c = new Chain"); c = new Chain; console.log("c.hasOwnProperty 'queue': " + (c.hasOwnProperty('queue')));
まとめ
- Webkitのconsole.logはオブジェクトが表示されるまでにディレイがあって、その途中でオブジェクトの中身を変更すると、変更後の内容が出力される
- CoffeeScriptのクラスの仕組みについて知るためにはJavaScriptのプロトタイプチェーン等に関する知識が必要。
JavaScriptについて勉強するにはパーフェクトJavaScriptがお勧めです。
パーフェクトJavaScript (PERFECT SERIES 4)
- 作者: 井上誠一郎,土江拓郎,浜辺将太
- 出版社/メーカー: 技術評論社
- 発売日: 2011/09/23
- メディア: 大型本
- 購入: 24人 クリック: 588回
- この商品を含むブログ (12件) を見る