JavaScriptのプロトタイプチェーンについてメモ

Published: 2016年3月17日 by tomsato

概要

JavaScript勉強シリーズ

JavaScriptのプロトタイプチェーンについてメモ
↑以前プロトタイプ継承についてまとめたがその続きとしてプロトタイプチェーンという機能について調べる

プロトタイプチェーンについて

プロトタイプ継承の記事から以下の前提をおさらいしておく

  • 全ての関数オブジェクトはprototypeという名前のプロパティを持つ
  • 関数オブジェクトのコンストラクタによって生成されたオブジェクトは全てprototypeオブジェクトへの(隠し)リンクを持つ

プロトタイプチェーンとはオブジェクトが他のオブジェクトのプロトタイプとなる連鎖のことを呼ぶ

prototypeオブジェクトを「親」と表現するとプロトタイプチェーンの動作として以下のようにプロパティを探す

  1. オブジェクト自身のプロパティ
  2. 1.のオブジェクトの「親」のオブジェクトのプロパティ(1で見つからなかったら)
  3. 2.のオブジェクトの「親」のオブジェクトのプロパティ(2で見つからなかったら)
  4. 探索が終わるまで繰り返す (「親」の終端に当たるのはObject.prototype)

「親」の終端がObject.prototypeであることを確認するための例

// クラス相当定義
// (JavaScriptにはクラスを作成する機能はないが便宜上クラスと呼ぶ)
function TestClass(){return;}

// コンストラクタ呼び出し
// TestClassインスタンスの作成
var obj = new TestClass();

// objの親オブジェクトはTestClass.prototypeである
// つまりobjはTestClass.prototypeを継承している
obj.__proto__ === TestClass.prototype; // true

// objの親の親オブジェクトはObject.prototypeである
// つまりobjやTestClass.prototypeはObject.prototypeを継承している
obj.__proto__.__proto__ === Object.prototype; // true

プロトタイプチェーンによってプロパティが連鎖していることを確認する例

// クラス相当定義
// (JavaScriptにはクラスを作成する機能はないが便宜上クラスと呼ぶ)
function TestClass(){return;}

TestClass.prototype.x = 3;
Object.prototype.y    = 5; // 例として書いているが基本的にこんな書き方はしない

// コンストラクタ呼び出し
// TestClassインスタンスの作成
var obj = new TestClass();

// Object.prototype -> TestClass.prototype -> obj と継承している
TestClass.prototype.__proto__ === Object.prototype;    // true
obj.__proto__                 === TestClass.prototype; // true
obj.__proto__.__proto__       === Object.prototype;    // true

// TestClass.prototypeはObject.prototypeを継承しているのでyが使える
print(TestClass.prototype.y); // 5
// objはTestClass.prototypeとObject.prototypeを継承しているのでx,yが使える
print(obj.x, obj.y);          // 3 5

prototypeと__proto__について

違いについて

prototype 関数オブジェクトが持つプロパティ、何らかのオブジェクトを持つ
__proto__ 上位オブジェクトのprototypeの参照を持つプロパティ

よってさっきの例のこの条件がtrueになる

// prototypeは関数オブジェクトだけ持つことに注意
typeof obj;       // object
typeof TestClass; // function
typeof Object;    // function

TestClass.prototype.__proto__ === Object.prototype;    // true
obj.__proto__                 === TestClass.prototype; // true
obj.__proto__.__proto__       === Object.prototype;    // true

ほとんど上の例を言い換えただけだが__proto__へのアドレスの代入のイメージ

function TestSuper() {}
TestSuper.prototype.a = 5;
TestSuper.prototype.__proto__ = Object.prototype;

// 3行目を実行してもしなくてもtrueになる
TestSuper.prototype.__proto__ === Object.prototype; // true

var obj = function() {};
obj.prototype = new TestSuper();
obj.prototype.__proto__ = TestSuper.prototype;

// 10行目を実行してもしなくてもtrueになる
obj.prototype.__proto__ === TestSuper.prototype; // true

// 以下違いについて
typeof obj.__proto__;
function
typeof obj.prototype;
object
// prototypeはオブジェクトで__proto__はprototypeがある場所を参照している

print(obj.prototype.a); // 5

参考

Share

最近の投稿

NetlifyのSplit TestingとFunctionsについて使い方をまとめる Split TestingはGitHubのブランチをベースにしたA/Bテストを行うための機能のことで、FunctionsはNetlifyでAWS Lambdaを使うことができる

NetlifyとはHTMLなどの静的コンテンツのみで構成されたWebサイトを閲覧できる形で配信するWebサービス GitHubやBitbucket、GitLabなどと連携して使うことができて、リポジトリにプッシュすることで自動でCI/CDを行うことができる、無料枠が豊富で独自ドメインを設定可能

WordPressからJekyll(GitHub Pages)に移行した手順をまとめる。 お金的な事情や使いやすさなどの理由で無料のJekyll+GitHub Pagesに移行した。JekyllとはMarkdown等から静的ページを生成する静的サイトジェネレータ

Scala開発のためにScalaらしさをまとめる 言語設計者の設計思想を元にScalaらしさについてまとめる オブジェクト指向と関数型の融合について

StorybookとはUI開発環境を提供するツール React、React Native、Angular、Vueなどをサポートしている ユーザーは独立した開発環境でコンポーネントを個別に作成して挙動の確認をテストできたり、コンポーネントを一覧にしてカタログ化できるので他の人に紹介する時に使えたりする

カテゴリ一覧

タグ一覧