ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript プロトタイプ チェーンに関するインタビューの質問の分析 (詳細)

JavaScript プロトタイプ チェーンに関するインタビューの質問の分析 (詳細)

不言
不言オリジナル
2018-09-19 17:12:065626ブラウズ

この記事の内容は、JavaScript プロトタイプ チェーンに関するインタビューの質問を分析したものです。必要な方は参考にしていただければ幸いです。

基本の前では、すべてのスキルは無駄になります。

#質問は次のようなものです。

コンソールの出力を記述する必要があります。

function Parent() {
            this.a = 1;
            this.b = [1, 2, this.a];
            this.c = { demo: 5 };
            this.show = function () {
                console.log(this.a , this.b , this.c.demo );
            }
        }
function Child() {
    this.a = 2;
    this.change = function () {
        this.b.push(this.a);
        this.a = this.b.length;
        this.c.demo = this.a++;
    }
}
        Child.prototype = new Parent(); 
        var parent = new Parent();
        var child1 = new Child();
        var child2 = new Child();
        child1.a = 11;
        child2.a = 12;
        parent.show();
        child1.show();
        child2.show();
        child1.change();
        child2.change();
        parent.show();
        child1.show();
        child2.show();

質問に含まれるナレッジ ポイント

    # #this は
  • プロトタイプ マシンのプロトタイプ チェーンを指します
  • クラスの継承
  • プリミティブ型と参照タイプの違い
  • 各知識ポイントは、個別の特別な研究のために取り出すことができます。


  • 問題を解決するために必要な知識ポイントの詳細

1. コンストラクターには、コンストラクターのプロトタイプ オブジェクトとインスタンスを指すプロトタイプ属性があります。同じ A プロトタイプ オブジェクトを共有します;

2。インスタンスが生成されると、メモリ内に新しいヒープ メモリが生成されます。インスタンス上の一般的な操作は、他のインスタンスに異なる領域を占有するため影響を与えません。 ;

3. 各インスタンスには、コンストラクターのプロトタイプ オブジェクトを指す暗黙的なプロトタイプ __proto__ があります。;

4.この指摘の問題は、一般的な状況にあります。以下を含めます:

4.1 オブジェクトメソッドとして使用される場合、それを呼び出す人を指します (この質問は主にこれに関係します)

4.2 関数として呼び出される場合、グローバルトップを指します-level 変数 window

4.3 コンストラクターとして 関数が呼び出されるとき、つまり new 演算子がインスタンスを生成するとき、コンストラクター内の this はインスタンスを指します。

4.4 呼び出し内で、およびapply メソッドでは、指定された this のバインディングが指定されたコンテキストとして表示されます。

5. リテラル定量メソッド (リテラルを直接量に変換する情報もあります。個人的には後者の翻訳の方が直感的でわかりやすいと思います)より鮮明です) オブジェクトと配列 (配列の本質もオブジェクトです) を割り当てるとき、それらはすべて参照です。つまり、スタック メモリで変数が生成され、その変数は次のアドレスを指します。リソース。

6. プロトタイプ チェーンの検索ルールは最短パスの原則に従います。つまり、最初にインスタンス属性を検索し、次にプロトタイプ チェーンに沿って Object.prototype と null が見つかるまで指定された属性を検索します。プロトタイプ チェーンの末尾、および検索対象のプロパティがプロトタイプ チェーン全体に存在しない場合は、未定義が返されます。

7 プリミティブ値の代入と参照型の代入ステートメントの詳細な違い。割り当て。######

質問の分析を開始します

1.parent.show()

基本的に説明することは何もありません。
値を直接取得することで答えを得ることができます1 [1,2,1] 5;

2.child1.show( )

Child のコンストラクターはもともと Child を指していました。質問では、
ChildJavaScript プロトタイプ チェーンに関するインタビューの質問の分析 (詳細) は明示的にプロトタイプ オブジェクトに設定されています。クラスの は、
Parent クラスのインスタンスを指します。これは、JavaScript オブジェクト指向プログラミングにおける一般的な 継承メソッドの 1 つです。ここで、Child.prototype は、クラス Parentを直接指すのではなく、インスタンス Parent を指すことに注意してください。コンソールに答えを出力して、11 [1,2,1] 5
JavaScript プロトタイプ チェーンに関するインタビューの質問の分析 (詳細)
これは驚くべきことです。混乱を招くのは、なぜ最後にthis.b が指す配列の列は 11
?JavaScript プロトタイプ チェーンに関するインタビューの質問の分析 (詳細)

ではなく

1 です。まず child1 がどのようになっているかを見てみましょう。

child1.show() メソッドが実行されると、Child1 は Child のインスタンスとして属性 a を持っているため、show() メソッドの this.a は this の値を直接指します。これも 11 であり、__proto__ が指すオブジェクトの a 属性を取得するためにプロトタイプ チェーンに沿って続行することはありません。b. child1 には属性 b がないので、これを探します。親の b 属性を取得します。その値は配列で、最初の 2 つの項目は定数であり、言うまでもなく、配列の最後の項目は参照であり、ここでのポインターは動的ではありません。 new Parent() 内のポインタ。 1 つのステップで 1 回実行され、parent.a が指すリソース (child1.__proto__ の a 属性が指すリソース) を指すことが決定されます。値1。


JavaScript プロトタイプ チェーンに関するインタビューの質問の分析 (詳細)拡張思考

次の点に注意してください:

コードの観点から見ると、child1.__proto__. b 配列 3 つの項目は child1.__proto__.a を指します。この時点で child1.__proto__.a の値を変更すると、child1.show() の結果に影響しますか?

  1. 答えは、影響がないということです。同じアドレスを指しているように見えるプロパティが異なる値を持つのはなぜでしょうか。親インスタンスの生成時に this.a がプリミティブ値 2 を指しているため、this.b の 3 番目の項目には実際にはプリミティブ値が代入されているため、一見すると参照型の代入のように見えますが、そうではありません。 。プリミティブ値の割り当てにより、新しいストレージ領域が開かれ、this.a と this.b[2] の値は等しくなりますが、ヒープ メモリ内の異なるアドレスを指します。さらに詳細な説明については、[多読] で推奨されているブログ記事を参照してください。

    JavaScript プロトタイプ チェーンに関するインタビューの質問の分析 (詳細)
    2. child1.__proto__.b 配列の 3 番目の項目も 11 を出力するようにする方法。

    インスタンス化後に変更します。
    Because in In親クラス定義では、b 属性配列の 3 番目の項目が a 属性の値を指します。これは、クラス内の this.a の値が存在する限り、この参照は親がインスタンス化される前に動的に指すことを意味します。親がインスタンス化される前に定義が変更されると、目的の効果を得ることができます。親でインスタンス化されている場合は、*.b[2] 属性の値を明示的に変更することしかできません。

  2. get/set メソッドの同期
もう 1 つの方法は、a 属性の get/set メソッドを設定することです。a 属性の値が変更されるたびに、b[2] の値が同期的に変更されます。コードと実行結果は次のとおりです:



  • ##3.child2.show ( )JavaScript プロトタイプ チェーンに関するインタビューの質問の分析 (詳細)
    JavaScript プロトタイプ チェーンに関するインタビューの質問の分析 (詳細)# 上記の説明を理解していれば、ここでも同じ答えが得られます: 12 [1,2,1] 5

# #その後、コードが実行されます: child1.change(); child2.change();

4.parent.show()

parent は Parent クラスのインスタンスであり、Child.prorotype は Parent クラスの別のインスタンスを指します。この 2 つはヒープ メモリ内の 2 つのリソースであり、相互に影響を与えません。したがって、上記の操作は親インスタンスには影響しません。 出力結果は変更されません: 1 [1,2,1] 5;

5.child1.show(),child2.show()

child1 がchange() メソッドを実行した後に何が変化しましたか?

this.b. Push(this.a)
this の動的ポインティング特性により、this.b は Child.prototype の b 配列を指し、this.a は child1 の a 属性を指すため、Child.prototype になります。 b は [1,2,1,11] になります;

this.a = this.b.length
この中の this.a と this.b のポイントステートメントは前の文と同じであるため、結果は child1.a が 4;

this.c.demo = this.a # になります。 ##child1 自身の属性には c 属性がないため、this.c は Child.prototype.c を指します。したがって、this.a の値はプリミティブ型です。値は割り当て操作中に直接割り当てられます。Child.prototype.c。デモの結果は
4 で、this.a は 5(4 1 = 5) に増加します。 次に、child2 は、change() メソッドを実行します。child2 と child1 は両方とも Child クラスのインスタンスであるため、それらのプロトタイプ チェーンは、同じ親インスタンスである同じプロトタイプ オブジェクト Child.prototype を指します。 したがって、プロトタイプ オブジェクトに対する

child2.change()

ステートメントのすべての効果は、child1this の最終出力結果に影響します。 b.push(this.a)

this の動的ポインティング機能では、this.b は Child.prototype の b 配列を指し、this.a は child2 の a 属性を指します。したがって、Child.prototype.b は

[1,2,1, 11,12];

this.a = this.b.length

になります。このステートメントの this.a と this.b の方向は前の文と一致しているため、結果は child2.a が 5;
this.c.demo = this.a ## になります。

#child2 自身の属性には c 属性がないため、ここでの this.c は Child.prototype.c を指すことになり、実行結果は Child.prototype.c.demo の値が child2 の値になります。 a、5、child2.a は最終的に 6 に増加します (5 1 = 6)。

次に、出力コマンドを実行すると、最終結果が出力されます。
child1.show( ):5 [1,2,1,11,12] 5

#child2.show() :6 [1,2,1,11,12] 5
#拡張思考問題を解いているときに、this.c.demo = this.a でエラーが発生しました。参照が渡されているのに、実際には値が渡されています。分析すると、this.a は元の値を指しているため、オブジェクト属性に元の値を代入することと同じであるため、代入後に child.c.demo の値は影響を受けないことがわかります。 child.a に変更します。 child.a が参照型の場合、結果はどのようになりますか?
ソース コードにいくつかの変更を加え、child.a がオブジェクト (つまり、参照型) を指すようにします。 次に、実行後、Child.prototype.c の値が次の値になることがわかります。 child1.a の値 現時点では child1.a の値は参照型であり、割り当てプロセスにより Child.prototype.c と child1.a が同じリソースのメモリ空間アドレスを指すようにするため、変更に応じて変更されます。元の型と参照型の詳細については、この記事の最後にある「詳細な読み方」にあるブログを参照してください。

収穫と反省

1. 基礎知識は本来、細部に散りばめられたものであり、最後まで戦う心構えで学ばなければなりません。 JavaScript プロトタイプ チェーンに関するインタビューの質問の分析 (詳細)
2. 基本的な知識は最も退屈であり、大きな工場に入りたい場合は越えなければならない敷居でもあります。緊急。私たちも初心者です。3 ~ 5 年経ってもフロントエンド アーキテクトになる人もいます。3 ~ 5 年経っても、イベントをボタンにバインドするために無限のフレームワークを使用している人もいます。を入れても、ほとんどの場合問題はありません。基礎はとても重要です!とても重要です!とても重要です!

以上がJavaScript プロトタイプ チェーンに関するインタビューの質問の分析 (詳細)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。