JavaScriptプロトタイプとプロトタイプチェーンを徹底的に理解する

JavaScriptプロトタイプとプロトタイプチェーンを徹底的に理解する

序文

プロトタイプとプロトタイプ チェーンに関する知識は、常に面接の焦点となってきました。それほど難しいことではありませんが、完全に理解するには、ある程度の努力が必要です。あなたの興味をそそる面接の質問を見てみましょう。

関数 User() {}
User.prototype.sayHello = 関数() {}
var u1 = 新しいユーザー();
var u2 = 新しいユーザー();
コンソールにログ出力します。 
console.log(User.prototype.constructor); 
console.log(User.prototype === Function.prototype); 
console.log(User.__proto__ === Function.prototype); 
console.log(User.__proto__ === Function.__proto__); 
コンソールにログ出力します。(u1.__proto__ === u2.__proto__); 
console.log(u1.__proto__ === User.__proto__); 
console.log(Function.__proto__ === Object.__proto__); 
console.log(Function.prototype.__proto__ === Object.prototype.__proto__); 
console.log(Function.prototype.__proto__ === Object.prototype); 

基礎を築く

すべての JavaScript オブジェクトは、基本的に new 関数を通じて作成されます。これには、オブジェクト リテラルの形式で定義されたオブジェクト (new Object() の構文糖衣に相当) も含まれます。

オブジェクト、配列などを含むすべての関数は、基本的に新しい関数を通じて作成されます。

すべての関数はオブジェクトです。

プロトタイプ

各関数には、プロトタイプであるプロパティ prototype があります。デフォルトでは、これは通常の Object オブジェクトであり、コンストラクターを呼び出すことによって作成されたインスタンスのプロトタイプです。

コンストラクタのプロパティ

JavaScriptには、プロトタイプからコンストラクタを指すプロパティもあります。コンストラクタ、つまりFunc.prototype.constructor --> Func

__プロト__

JavaScript のすべてのオブジェクト (null を除く) には、オブジェクトのプロトタイプを指す __proto__ プロパティがあります。

関数 User() {}
var u1 = 新しいユーザー();
// u1.__proto__ -> User.prototype
console.log(u1.__proto__ === User.prototype) // true

明らかに、インスタンスの __proto__ プロパティはコンストラクターのプロトタイプを指しているので、複数のインスタンスの __proto__ は同じプロトタイプを指すのでしょうか?

var u2 = 新しいユーザー();
console.log(u1.__proto__ === u2.__proto__) // 真

複数のインスタンスの __proto__ がすべてコンストラクターのプロトタイプを指している場合、インスタンスが特定の方法でプロトタイプのメソッド、プロパティなどにアクセスできると、プロトタイプでプログラミングして継承の効果を実現できます。

プロトタイプとプロトタイプ チェーンの関係図を更新し続けましょう。

プロトタイプチェーン

インスタンス オブジェクトが属性を探しているときに、見つからない場合は、__proto__ に従って、オブジェクトに関連付けられたプロトタイプを検索します。それでも見つからない場合は、最上位レベルが見つかるまで、プロトタイプのプロトタイプを検索します。これがプロトタイプ チェーンの概念です。

インタビューの質問を使用したプロトタイプ チェーンの例をいくつか見てみましょう。

  1. u1.sayHello():
    u1にはsayHelloメソッドがないので、u1.__proto__(User.prototype)にアクセスしてsayHelloメソッドに正常にアクセスします。
  2. u2.toString()
    u2、User.prototypeにはtoStringメソッドがなく、User.prototypeも通常のオブジェクトなので、User.prototype.__proto__(Object.prototype)を探し続けてtoStringメソッドを正常に呼び出します。

改善する

上記を学んだ後、ほとんどの面接の質問に答えることができます。例えば、次のようなものです。

関数A() {}
関数B(a) {
    これは、
}
関数C(a) {
    もし(a){
        これは、
    }
}
プロトタイプa = 1;
B.プロトタイプ.a = 1;
C.プロトタイプ.a = 1;

コンソール.log(新しいA().a); //1
console.log(新しい B().a); //未定義
コンソール.log(新しいC(2).a); //2

しかし、Function.__proto__ === Object.__proto__、Function.prototype.__proto__ === Object.prototype.__proto__ など、記事の元の面接の質問を解決するにはまだ何かが欠けています。 1 つずつ取り組んでみましょう。

Object.__proto__、Object.prototype、Object.prototype.__proto__

  • Object はコンストラクタです。2 番目の部分では、すべての関数は new Function を通じて作成されると述べました。したがって、Object は Function のインスタンス、つまり Object.__proto__ --> Function.prototype と同等です。
  • Object.prototype は、プロトタイプ チェーンの最上位にある Object コンストラクターのプロトタイプです。Object.prototype.__proto__ には指す上位プロトタイプがないため、その値は null になります。
// 要約:
Object.__proto__ --> Function.prototype
Object.prototype.__proto__ --> null

Function.__proto__、Function.prototype、Function.prototype.__proto__

  • Function.prototype は Function のプロトタイプであり、前述の Object.__proto__ など、すべての関数インスタンスのプロトタイプです。
  • Function.prototypeは通常のオブジェクトなので、Function.prototype.__proto__ --> Object.prototype
  • Function.__proto__: __proto__ は、それを作成したコンストラクターのプロトタイプを指します。では、Function を作成したのは誰でしょうか?
    • 仮説: 関数オブジェクトもオブジェクトなので、Function.__proto__ は Object.prototype を指しますか?前述のとおり、Object.__proto__ --> Function.prototype です。 Function.__proto__ -> Object.prototype の場合、誰が誰を作成したのか常に奇妙に感じるので、いくつかテストを行いました。

実践により、Object.__proto__ --> Function.prototype のみが存在することが証明されます。

一生懸命考えましたが、何も思いつきません。Function は岩の間から飛び出してきた猿なのでしょうか?そこで、ランダムにテストをいくつか実行したところ、予想外に手がかりが見つかりました。

上記から、次の結論が導き出せます: Function.__proto__ --> Function.prototype

関数は何によっても作成されず、JS エンジンの起動時にメモリに追加されます。

要約する

最後に、プロトタイプとプロトタイプ チェーンに関する知識を図にまとめます。

  1. すべての関数(Functionを含む)の__proto__はFunction.prototypeを指します。
  2. カスタムオブジェクトインスタンスの__proto__はコンストラクタのプロトタイプを指します。
  3. 関数のプロトタイプの__proto__はObject.prototypeを指します。
  4. Object.prototype.__proto__ --> null

あとがき

知識の海は、想像以上に広大であることがよくあります。私はプロトタイプとプロトタイプ チェーンを何度も研究してきましたが、より包括的かつ完全に理解できたと思います。しかし、この面接の質問に遭遇した後、私が学んできたことは単なる一分野に過ぎず、JS には発掘されるのを待っている深い宝物が本当にたくさんあることに気づきました。学びに終わりはありません。お互いに励まし合いましょう。

最後に、自信を高めるための簡単な面接の質問をご紹介します。

var F = 関数 () {}
Object.prototype.a = 関数 () {}
Function.prototype.b = 関数 () {}

var f = 新しい F();

コンソールにログ出力します。

// プロトタイプチェーン // f.__proto__ --> F.prototype --> Object.prototype
// F.__proto__ --> Function.prototype --> Object.prototype

JavaScript プロトタイプとプロトタイプ チェーンに関するこの記事はこれで終わりです。JavaScript プロトタイプとプロトタイプ チェーンに関するより関連性の高いコンテンツについては、123WORDPRESS.COM で以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • JavaScript のプロトタイプとプロトタイプチェーンの詳細な説明
  • JavaScriptプロトタイプチェーンの詳細な説明
  • JavaScript プロトタイプとプロトタイプチェーンの詳細
  • js のプロトタイプ、プロトタイプ オブジェクト、プロトタイプ チェーンの包括的な分析
  • JavaScript プロトタイプとプロトタイプチェーンの深い理解

<<:  CSS 標準: vertical-align プロパティ

>>:  Docker デプロイメント Consul 構成プロセスの分析

推薦する

Windows 10 での MySQL 8.0.16 のインストールと設定のチュートリアル

この記事では、参考までにMySQL 8.0.16のインストールと設定方法のグラフィックチュートリアル...

VUEの基本を理解するのに役立つ記事

目次VUEとはVueのコアプラグインVueルーターヴュークスアクシオス要素UI Vue フロントエン...

JavaScript の手ぶれ補正とスロットリングの詳細な説明

目次デバウンススロットル要約するデバウンス定義: スクロール イベントなど、短時間に連続してトリガー...

Mac M1 での Nginx のマルチサイト構成の実装

注: nginxはbrew経由でインストールされますウェブサイトのルートディレクトリ: /opt/h...

このリファレンスとJavaScriptのカスタムプロパティの詳細な説明

目次1. このキーワード2. カスタム属性3. 包括的なケース1:タブの実装付録要約する1. このキ...

Reactの状態管理の3つのルールのまとめ

目次序文No.1 焦点No.2 複雑な状態ロジックの抽出No.3 複数状態操作の抽出要約する序文Re...

「いいね!」機能では MySQL と Redis のどちらを使用すればよいでしょうか?

目次1. 初心者が陥りがちな間違い2. Iteratorのremove()メソッドを使用する3. f...

docker compose idea CreateProcess error=2 システムは指定されたファイルを見つけることができません

Docker の作成Compose の紹介Compose は、マルチコンテナ Docker アプリケ...

MySQL における explain の役割の詳細な説明

1. MYSQLインデックスインデックス: MySQL がデータを効率的に取得するのに役立つデータ構...

例によるMySql CURRENT_TIMESTAMP関数の分析

時間フィールドを作成するときデフォルトのCURRENT_TIMESTAMPデータを挿入する際、このフ...

Tomcat のメモリ構成の正しい姿勢についての簡単な説明

1. 背景多くのブログや記事を読みましたが、JVM のメモリ割り当て方法に関する包括的な記事は見つか...

同じレベルの要素で Position:fixed と margin-top を一緒に使用する場合の CSS の問題

問題の説明CSS を使用して上部の固定効果を実現したいと思います。 margin-top と pos...

Reactはルーティングを使用してログインインターフェースにリダイレクトします

前回の記事では、webpack と react 環境を設定した後、ログイン インターフェースとその後...

Dockerイメージのインポートとエクスポートの実装

GitLabのDocker使用法gitlab ドッカー起動コマンド docker run -d -p...

モバイルの赤い封筒の雨機能ページを実装するための JavaScript HTML

この記事の例では、モバイル紅包雨機能ページを実現するためのHTMLの具体的なコードを共有しています。...