JavaScriptプロトタイプチェーン(1)プロトタイプチェーン図示ツール

ラベル:

簡単に理解できそうに思ったのに全く理解が進まないJavaScriptコードを図示してくれるツールをようやくみつけました。

プロトタイプチェーン図示ツールObject Playground


Object Playground: The Definitive Guide to Object-Oriented JavaScript

英語ですがJavaScriptについての解説ビデオもついています。

JavaScript | MDNをいくら読んでも理解が進まなかったプロトタイプチェーンについてこのビデオでわかった気がします。

ビデオののっけからでてくるJavaScriptの型の分類でObjectがPrimitive Typesに分類されてるのは間違いだそうです。(YouTubeのコメントで作者が回答されています。)


ビデオの下にでているのがObject Visualizer:オブジェクトビジュアライザー(とビデオでは言っています)です。

thisのプロパティからプロトタイプチェーンの図示が始まる


JavaScriptコードを入力して「Click to Evaluate」をクリックするとプロトタイプチェーンが表示されます、、、というわけにはいきませんでした。

「this」が表示されるだけです。



ビデオの下にあるボタンをクリックするとサンプルが表示されますのでそれの最後をみてみるとすべてのコードの最後はthisのプロパティに代入してありました。
this.g = { h: "baz" };
this.instance = new MyClass();
this.instance = new Child();
this.instance = new Ninja(true);
this.jdls = jdls;
それぞれこんな感じで一見グローバルスコープでthisが使われています。

この「this」のプロパティのプロトタイプチェーンを図示してくれるようです。

どこかに解説があるか探してみましたが見つけられませんでした。

YouTubeのコメントには絶賛するコメントの合間に、自分で書いたJavaScriptコードが図示されない、と書いてあるものがいくつかありますが、だれも回答していません。

とりあえずthisのプロパティからプロトタイプチェーンが始まる、ということはビデオにでてくる通りの図にならず、最初にthisから始まることになります。

例えばビデオの7:10頃にでてくるプロトタイプチェーンの例をObject Visualizerで図示化するときは図示したいプロトタイプチェーンの最初をグローバルスコープのthisのプロパティに設定します。
var parent = {
    get: function fn() {
         return this.val;
    },
    val: 42
}
var child = Object.create(parent);
child.val = 3.14159

parent.get(); //→42
child.get(); //→3.14159
this.parent = parent;
12行目を図示のために追加しました。

parentオブジェクトが図示されました。

2行目のfn()は無名関数にしてもJavaScriptとしては動作しますがそうするとObject Visualizerでは<anon>と表示されてわかりにくいです。

プロトタイプチェーンの始まりの最初の「this」はグローバルスコープのthisではない


プロトタイプチェーンの開始点となるthisはグローバルスコープのthisではないようです。

WSH JScriptでJavaScriptのお勉強(関数定義、クロージャ、this)で使った例(this - JavaScript | MDN)でみてみます。
function Car(brand) {
    this.brand = brand;
}
Car.prototype.getBrand = function () {
    return this.brand;
}
var foo = new Car("toyota");
this.foo_getBrand=foo.getBrand();  // foo.getBrand()の結果→"toyota"
var brand = "not a car";
var bar = foo.getBrand;
this.bar=bar();  // bar()の結果→"not a car"

this.foo_getBrandはちゃんと"toyota"が返っていますがthis.barはundefinedになっています。

this.brand=brand、では"not a car"が返ってきます。

このオブジェクトビジュアライザーではbrandとbar()は同一のプロトタイプチェーンにあるとは認識されていないようです。

pq@pq-VirtualBox:~$ nvm use stable
Now using node v0.12.7 (npm v2.11.3)
pq@pq-VirtualBox:~$ node
> function Car(brand) {
...     this.brand = brand;
... }
undefined
> Car.prototype.getBrand = function () {
...     return this.brand;
... }
[Function]
> var foo = new Car("toyota");
undefined
> var brand = "not a car";
undefined
> var bar = foo.getBrand;
undefined
> bar();
'not a car'
> this.bar();
'not a car'

node.jsのコンソールではbar()でもthis.bar()でも"not a car"が返ってきます。


グローバルスコープを明示的にthisで書くとthis.bar()の結果も返ってきますがグラフの「this」とは区別できないのでグラフのthisオブジェクトのノードに表示される項目が煩雑になってしまいます。

linuxBean14.04(58)Object PlaygroundをローカルにインストールでやったようにローカルにObject Playgraoundをインストールしてuser_code.jsを編集して、グラフに描画されるオブジェクトを「this」から「context」に変更するとグローバルスコープのthisと区別できるようになります。

明示的に書いたグローバルスコープのthisはページをリロードしないとリセットされないことに注意が必要です。

参考にしたサイト


Object Playground: The Definitive Guide to Object-Oriented JavaScript
JavaScriptプロトタイプチェーン図示ツール。

JavaScript | MDN
Mozilla Developer NetworkによるJavaScriptのマニュアル。

this - JavaScript | MDN
MDNによるthisの解説。

次の関連記事:JavaScriptプロトタイプチェーン(2)プロトタイプチェーンとプロパティシャドウィング

PR

0 件のコメント:

コメントを投稿