JSのプロトタイプとプロトタイプチェーン再ソート再び、その後、手はフローチャート、描いた秘密のプロトタイプとプロトタイプチェーンこの絵に隠されています。給付は、描画処理中にこの知識を、より徹底した理解がより印象的になりながら両方、状況の知識の彼の把握をテストするために、中に描かれたプロセス・フロー図である、それぞれの興味男が来たことをお勧めします個人的に一度。
、プロトタイプチェーンの明確な理解に向かって移動多重継承を構築するには、3つのコンストラクタ、それぞれ人、ChinaPersonを作成し、ProvincePersonするためには、それらの間の継承関係は次のとおりです。ProvincePersonはChinaPersonを継承し、ChinaPersonは人を継承します。我々は、次
最初のコードを貼り付け、内部のコンストラクタ関数とプロトタイプで、それぞれ、親の上を継承に基づいて各サブコンストラクタは、独自のカスタム属性とメソッドを追加します。加えて、書くことや人のprototypeプロパティに同じ名前の内部コンストラクタおよび方法、同じ名前のメソッドの名前を検証するために使用されている場合、コンストラクタ関数の方法と優先的に実行プロトタイプ法; ProvincePerson親メソッドから継承して書き換えに、オブジェクト指向のマルチステート特性を示す概略側面。
/ * * * JavaScriptのマルチレベルの継承及び多型、プロトタイプとプロトタイプチェーンを反映 * * / // 1.1コンストラクタ:人(人) 機能人(名前){ この .nameの=名名:?「人間」を、 この .methodPerson = 関数(){ にconsole.log( "人物コンストラクタメソッドmethodPerson - > Iタグ:" + この.nameの); } はconsole.log(「人物構成******** 「********初期化); } // プロトタイプ人に追加された属性およびメソッド Person.prototype.age = 18である。 Person.prototype.run = 関数(){ にconsole.log(「人試作RUN - >名:」+ この .nameの+「年齢:」+ この .age +「陽気RUN」); } // 問題:プロパティとメソッド内のプロトタイプコンストラクタの場合そして、同じ名前のプロパティとメソッド、コンストラクタ、オブジェクトのどのインスタンスの実装プロパティとメソッドを呼び出しますか? // オブジェクトのインスタンスを呼び出し人と人コンストラクタのプロトタイプ、の名前の名前は? Person.prototype.name = "子孫" ; Person.prototype.methodPerson = 関数(){ にconsole.log( "人物methodPersonプロトタイプ法- >タグ:" + この .nameの+ "年齢" + 本。年齢); } // 1.2コンストラクタ:中国の人々 (ChinaPerson)、人から継承された 機能ChinaPerson(名前、スキン){ Person.call(これ、名);人コンストラクタは親を呼び出し 、この .skin =スキン皮膚: "黄"?; この .methodChinaPerson = 関数(){ にconsole.log( "ChinaPerson方法methodChinaPerson内部コンストラクタ- >色:" + この .skin + "ラベル: "+ この.nameの); } はconsole.log( "コンストラクタは「ChinaPerson ******** ********を初期化); } // 設定ChinaPersonプロトタイププロトタイプ人、かなり。人でChinaPerson承継 ChinaPerson.prototypeは= ; Object.create(Person.prototype) // 自分自身に設定され、新たなプロトタイプコンストラクタポイントを ChinaPerson.prototype.constructor = ChinaPerson; // ChinaPersonは、プロトタイプのカスタムプロパティとメソッドを追加します ChinaPerson.prototype.heroは=「タン」; ChinaPerson.prototype.write = 機能(){ はconsole.log(書き込み「ChinaPersonプロトタイプメソッドは- >私は笑ってから日Hengdao、肝胆運命は誰崑です! ? "+ この .hero +"、ラベル"+ この .nameの+"、スキン:「+ この.skin); } // 1.3コンストラクタ:ProvincePerson、ChinaPersonのから継承された 機能ProvincePerson(名前、スキン、COUNT){ ChinaPerson.call(この、名前、スキン); //は、親クラスのコンストラクタを呼び出すChinaPerson この .countは= COUNTのCOUNT:?8000 ; この .methodProvincePerson = 機能(){ コンソール。ログ("コンストラクタメソッドmethodProvincePerson内部ProvincePerson - >数:" + この .count + "WAN、カラー:" + この .skin + "レーベル:" + この.nameのは); } // 親から継承オーバーライドmethodChinaPersonダウンの方法 この .methodChinaPerson = 関数(){ にconsole.log( "親をオーバーライドProvincePersonコンストラクタメソッド.... methodChinaPerson" ); } はconsole.log(「********構成ProvincePerson ********「初期化) } // 設定点ChinaPerson ProvincePersonプロトタイププロトタイプ等価コンストラクタProvincePersonがChinaPerson継承 ProvincePerson.prototypeは= Object.create(ChinaPerson.prototype)を、 セットポイント新しいプロトタイプコンストラクタ自分の// = ProvincePerson.prototype.constructor ProvincePerson; // ProvincePersonプロパティおよびメソッドを追加カスタムプロトタイプに ProvincePerson.prototype.feature = "長沙豆腐" ; ProvincePerson.prototype.eat = 関数(){ にconsole.log(「プロトタイプProvincePerson方法食べる- >ラベル: "+ この .nameの+"、ローカルスナックは"+ この .feature +"、ヒーロー: "+ この .hero +"、スキン:「+ この.skin); } / / 親クラスプロトタイプから継承されたメソッドをオーバーライドするダウン ProvincePerson.prototype.write = 関数(){ にconsole.log(「親プロトタイプ法ライトから継承オーバーライドProvincePersonプロトタイプ- > ... ^ _ ^」); }
上記のコード構造マッピング関数プロトタイプチェーン関係の組み合わせ、以下に示すように:
地図上に記載されており、プロトタイプチェーンの知識ポイントは要約します。
- ProvincePerson、ChinaPerson、人3つのカスタムコンストラクタ、関数、オブジェクト2つのシステムはコンストラクタです。
- プロトタイプチェーン方向(方向探して親)です:ProvincePerson - > ChinaPerson - >人 - >オブジェクト - >ヌル;機能 - >オブジェクト - >ヌル。
- OBJ上の図は、オブジェクトコンストラクタProvincePersonのインスタンスであり、矩形がコンストラクタ、コンストラクタを表す六角形のプロトタイプオブジェクトを表し、赤い点線は、親に探し__proto__プライベートプロトタイププロトタイプによってオブジェクト・インスタンスの属性を表します。
- プロトタイプの属性コンストラクタで、__ proto__がオブジェクトインスタンスコンストラクタのプロパティです。
- オブジェクト、すなわち、対象点__proto__プロパティコンストラクタプロトタイププロパティの例インスタンスオブジェクト.__ proto__ = コンストラクタ.prototype 。
- __proto__暗黙のプロトタイプ、通常は直接使用することは推奨しません、通常Object.getPrototypeOf(オブジェクト)オブジェクトインスタンスのプロトタイプを取得します。
- __proto__オブジェクトのオブジェクトインスタンスとプロトタイプコンストラクタであります
- オブジェクト、すなわち、対象点__proto__プロパティコンストラクタプロトタイププロパティの例インスタンスオブジェクト.__ proto__ = コンストラクタ.prototype 。
- 集中ノック:
- 関数は新しいキーワードで呼び出された場合、そのようOBJ =新ProvincePerson()VARとして、コンストラクタを呼ばれます。その後ProvincePersonは、コンストラクタはクラステンプレートであると呼ばれます。
- 関数は、新しいキーワード、ダイレクトコールを使用しない場合は、などProvincePerson()、オブジェクト()、関数()、などの一般的な機能は、ですので、通常の関数を呼び出すためにそれらを使用します。
- すべての一般的な機能は、それらが機能している通常の関数呼び出しオブジェクトインスタンスなどのオブジェクト、関数として、コンストラクタ関数インスタンスオブジェクトです。
- 彼らは二重のアイデンティティを持っているので、それは、関数のプロトタイププロパティでなく、__proto__プロパティ理由でもあります。
- 彼らは新しいキーワードを使用する可能性があるとして、最初の二重生活、そして、彼らはコンストラクタされ、prototypeプロパティがあります。
- 彼らは新しいキーワード、ダイレクトコールを使用しないように、第2の二重生活、この時間は、彼らは、オブジェクトのコンストラクタ関数のインスタンスなので、この時間は、彼らは__proto__プロパティを持っています。
- 特別な存在としての機能は、特別にすることであるFunction.prototypeのproto__ .__ =関数 プロトタイプコンストラクタ(プロトタイプ)と機能(__proto__)の試作例として、その共通オブジェクトとして、すなわち同一のオブジェクトを指し示します。
- コンストラクタプロトタイプコンストラクタプロパティポイントコンストラクタインスタンスオブジェクトコンストラクタはまた、コンストラクタを対象とする、すなわち、オブジェクトコンストラクタ関数.prototype.constructorのインスタンス= .constructorコンストラクタのコンストラクタ=
- 親クラスのコンストラクタから継承されたコンストラクタは、親はすべての外部の属性やパーティーコンストラクタメソッドを持つことになりますし、親のプロトタイプのプロパティとメソッドが含まれ;
- コンストラクタ関数メソッドまたはプロパティ場合、プロパティまたはそのプロトタイプ、コンストラクタ関数またはメソッド呼び出し属性の優先度に同じ名前のメソッド、子コンストラクタはプロパティとメソッド継承を書き換えることができます。
- コンストラクタやプロトタイプチェーンを介したすべてのオブジェクトは、起源をトレース、最後のオブジェクトの祖先です。すなわち、すべてのコンストラクタは、間接的な子または子のオブジェクトです。プロトタイププロトタイプオブジェクトがnullの場合、ここでの究極のフィナーレです!
これらの点についての知識は、上記のコードに基づいて、再度、いくつかのテストコードをテストすることです。プロトタイプチェーン関係の最初のテストコード:
//测试一下 var pro1 = Person.prototype, pro2 = ChinaPerson.prototype, pro3 = ProvincePerson.prototype; //ProvincePerson原型的原型 === ChinaPerson的原型 var pro3_china = Object.getPrototypeOf(pro3); //ProvincePerson原型的原型的原型 === Person的原型 var pro3_person = Object.getPrototypeOf(pro3_china); //ProvincePerson原型的原型的原型的原型 === Object的原型 var pro3_object = Object.getPrototypeOf(pro3_person); //Function和Object作为普通函数时是构造函数Function的实例对象,获取这两个实例对象的原型 var pro_function = Object.getPrototypeOf(Function), pro_object = Object.getPrototypeOf(Object); console.log("************* 原型链测试 start **********") console.log("构造函数ProvincePerson继承自ChinaPerson, 构造函数ChinaPerson继承自Person, Person继承自Object") console.log("Object --> Person --> ChinaPerson --> ProvincePerson") console.log("Person.原型:", pro1); console.log("ChinaPerson.原型:", pro2); console.log("ProvincePerson.原型:", pro3); console.log("ProvincePerson.原型.原型: ", pro3_china); console.log("ProvincePerson.原型.原型.原型: ", pro3_person); console.log("ProvincePerson.原型.原型.原型.原型:", pro3_object); console.log("ProvincePerson.原型.原型 === ChinaPerson.原型 --> ", pro3_china === pro2); console.log("ProvincePerson.原型.原型.原型 === Person.原型 --> ", pro3_person === pro1); console.log("ProvincePerson.原型.原型.原型.原型 === Object.原型 --> ", pro3_object === Object.prototype); console.log("Function.prototype === Function.__proto__ --> ", Function.prototype === pro_function); console.log("Object.__proto__ === Function.prototype --> ", pro_object === Function.prototype); console.log("************ 测试 end ************\n") /* 测试结果: ************* 原型链测试 start ********** 构造函数ProvincePerson继承自ChinaPerson, 构造函数ChinaPerson继承自Person, Person继承自Object Object --> Person --> ChinaPerson --> ProvincePerson Person.原型: {age: 18, run: ƒ, name: "炎黄子孙", methodPerson: ƒ, constructor: ƒ} ChinaPerson.原型: Person {constructor: ƒ, hero: "谭嗣同", write: ƒ} ProvincePerson.原型: ChinaPerson {constructor: ƒ, feature: "长沙臭豆腐", eat: ƒ, write: ƒ} ProvincePerson.原型.原型: Person {constructor: ƒ, hero: "谭嗣同", write: ƒ} ProvincePerson.原型.原型.原型: {age: 18, run: ƒ, name: "炎黄子孙", methodPerson: ƒ, constructor: ƒ} ProvincePerson.原型.原型.原型.原型: {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …} ProvincePerson.原型.原型 === ChinaPerson.原型 --> true ProvincePerson.原型.原型.原型 === Person.原型 --> true ProvincePerson.原型.原型.原型.原型 === Object.原型 --> true Function.prototype === Function.__proto__ --> true Object.__proto__ === Function.prototype --> true ************ 测试 end ************ */
测试结果截图:
再来一份对于多级继承和重写展示的测试代码:
//第二波测试,测试构造函数的继承 和 多态(重写从父级继承下来的属性或方法) console.log("\n************* 继承和重写 start ************"); console.log(">>>>>>准备创建一个Person实例对象>>>>>"); var per = new Person("王大锤"); per.methodPerson(); per.run(); console.log("*****Person实例对象测试结论:构造函数和原型有同名属性或方法,实例对象优先调用构造函数的属性或方法*****\n"); console.log("\n>>>>>准备创建一个ChinaPerson实例对象,ChinaPerson继承了Person >>>>>"); var chObj = new ChinaPerson("中国人", "黄色"); chObj.methodChinaPerson(); chObj.write(); chObj.methodPerson(); chObj.run(); console.log("*****ChinaPerson实例对象测试结论:继承自父类Person, 拥有父类所有对外的构造函数里面和原型里面的属性和方法\n"); console.log("\n>>>>>准备创建一个ProvincePerson实例对象,ProvincePerson继承了ChinaPerson>>>>>"); var proObj = new ProvincePerson("湖南人", "黄色", 888); proObj.methodProvincePerson(); proObj.eat(); proObj.methodChinaPerson(); proObj.write(); proObj.methodPerson(); proObj.run(); console.log("*****ProvincePerson实例对象测试结论:拥有父级和父级的父级的所有对外的,包括构造函数里面和原型里面的属性和方法;另外也可以对父级属性或方法进行重写"); console.log("************ 测试 end ************\n"); /* 测试结果打印日志: ************* 继承和重写 start ************ >>>>>>准备创建一个Person实例对象>>>>> ********Person 构造函数 初始化******** Person构造函数里面的方法methodPerson-->我的标签:王大锤 Person原型方法run-->name: 王大锤, age: 18, 欢快的run *****Person实例对象测试结论:构造函数和原型有同名属性或方法,实例对象优先调用构造函数的属性或方法***** >>>>>准备创建一个ChinaPerson实例对象,ChinaPerson继承了Person >>>>> ********Person 构造函数 初始化******** ********ChinaPerson 构造函数 初始化******** ChinaPerson构造函数里面的方法methodChinaPerson-->肤色:黄色, 标签: 中国人 ChinaPerson原型里面的方法write-->我自横刀向天笑,去留肝胆两昆仑!is who? 谭嗣同, 标签: 中国人, skin: 黄色 Person构造函数里面的方法methodPerson-->我的标签:中国人 Person原型方法run-->name: 中国人, age: 18, 欢快的run *****ChinaPerson实例对象测试结论:继承自父类Person, 拥有父类所有对外的构造函数里面和原型里面的属性和方法 >>>>>准备创建一个ProvincePerson实例对象,ProvincePerson继承了ChinaPerson>>>>> ********Person 构造函数 初始化******** ********ChinaPerson 构造函数 初始化******** ********ProvincePerson 构造函数 初始化******** ProvincePerson构造函数里面的方法methodProvincePerson-->数量:888万, 肤色:黄色, 标签:湖南人 ProvincePerson原型里面的方法eat-->标签:湖南人, 地方小吃是:长沙臭豆腐, hero: 谭嗣同, skin: 黄色 ProvincePerson构造函数里面重写父级方法methodChinaPerson.... ProvincePerson原型里面重写从父级原型继承的write方法-->。。。。^_^ Person构造函数里面的方法methodPerson-->我的标签:湖南人 Person原型方法run-->name: 湖南人, age: 18, 欢快的run *****ProvincePerson实例对象测试结论:拥有父级和父级的父级的所有对外的,包括构造函数里面和原型里面的属性和方法;另外也可以对父级属性或方法进行重写 ************ 测试 end ************ */