基礎学習-JSでの継承
8933 ワード
の原因となる
最近node-jsonwebtokenを使って次のコードを見つけました.とてもきれいだと思います.そこで、関連コードを探してみました.
コードアドレス、ここをクリック
後でこのセグメントコードを分析します.
MDNの継承に関するセクションを見つけます(継承はプロトタイプチェーンでは高度なチュートリアルです).
JavaScriptでの継承は
継承とは?
継承はオブジェクト向けのソフトウェアの一つの概念である.オブジェクトに向かう2つの特徴は,それぞれ多態,分装である.継承は,自雷に親の属性やメソッドを持たせるか,再定義,追加属性やメソッドなどである.
wikipedia)
継承メソッド
プロトタイプチェーン継承
この継承方式は
上記の例で説明する必要があることは、親属性を使用する場合はJSのデータ型変化ルールに従い、元の値(Primitive values)は変更不可(not mutation)、オブジェクトは変更されます.このJSストレージタイプが決定します.元の値は毎回新しい値を返しますが、オブジェクトはメモリ内の領域アドレスを表し、アドレスは変わりません.具体的には、内部データが異なる場合でも、同じです.これはJSにおける深浅コピー問題を設計し,その後に触れる.
サブクラスコンストラクション関数を使用して継承
この方法は、まず、
ここではParentで
メリットプロトタイプチェーン継承、サブクラスが親参照属性にアクセスする問題 を解決した.子クラス初期化時に親クラスに を渡すことができる.マルチ継承( を実現する.
欠点サブクラスインスタンス に等しくない.親プロトタイプチェーンを継承できない方法 初期化のたびに親関数の初期化が必要であり、パフォーマンスが悪い .
ここで使用
組合せ継承(プロトタイプチェーン+サブクラス構築関数)-1
ここではプロトタイプチェーン継承と構造関数の利点を融合させた.しかし、欠点は、サブクラスを作成するときに2回の親クラスを呼び出すコンストラクション関数が呼び出されることです.上記の親参照共有 子クラス親クラスのすべての属性とメソッド を取得できます.
グループ継承-2
ここでは、子の
グループ継承-3
ここで、上記との違いは、
このような方式の継承を通じて、現在では最も完璧な方式であり、以前の多くの問題も解決されている.
ES 6のextendsキーワード
この方式は現在のes 6の方式で、欠点は互換性で、すべてのブラウザがes 6と完璧に互換性があるわけではありません.しかし、他の言語と一致した継承文法が明らかで、分かりやすいです.
実際のJSはプロトタイプチェーンで継承されているので、ここでは最終的に次のコードにコンパイルされます.
これはBabelコンパイルの結果であり,プロトタイプチェーンによって実現されるかを見ることができる.
次の図を見てください.
ここでコードとコンビネーション継承3は似ていますよ
詳細:
https://www.quora.com/What-is...
https://segmentfault.com/a/11...
最近node-jsonwebtokenを使って次のコードを見つけました.とてもきれいだと思います.そこで、関連コードを探してみました.
コードアドレス、ここをクリック
var JsonWebTokenError = function (message, error) {
Error.call(this, message);
if(Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor);
}
this.name = 'JsonWebTokenError';
this.message = message;
if (error) this.inner = error;
};
JsonWebTokenError.prototype = Object.create(Error.prototype);
JsonWebTokenError.prototype.constructor = JsonWebTokenError;
module.exports = JsonWebTokenError;
後でこのセグメントコードを分析します.
MDNの継承に関するセクションを見つけます(継承はプロトタイプチェーンでは高度なチュートリアルです).
JavaScriptでの継承は
によって実現される.JSでの継承についてお話しします継承とは?
継承はオブジェクト向けのソフトウェアの一つの概念である.オブジェクトに向かう2つの特徴は,それぞれ多態,分装である.継承は,自雷に親の属性やメソッドを持たせるか,再定義,追加属性やメソッドなどである.
wikipedia)
継承メソッド
プロトタイプチェーン継承
//
function Parent(name, age) {
this.name = name,
this.age = age,
this.play = [1, 2, 3]
this.setName = function () { }
}
Parent.prototype.setAge = function () { }
//
function Child(price) {
this.price = price
this.setScore = function () { }
}
Child.prototype = new Parent() //
var s1 = new Child(15000)
var s2 = new Child(14000)
console.log(s1,s2)
この継承方式は
Child.prototype
をParent
オブジェクトに直接設定し,サブクラスはプロトタイプチェーンを介して親のすべての属性と方法にアクセスできるようになった.その後、新しい属性を追加するには、Child.prototype = new Parent()
の後にある必要があります.そうしないと、上書きされます.上記の例で説明する必要があることは、親属性を使用する場合はJSのデータ型変化ルールに従い、元の値(Primitive values)は変更不可(not mutation)、オブジェクトは変更されます.このJSストレージタイプが決定します.元の値は毎回新しい値を返しますが、オブジェクトはメモリ内の領域アドレスを表し、アドレスは変わりません.具体的には、内部データが異なる場合でも、同じです.これはJSにおける深浅コピー問題を設計し,その後に触れる.
サブクラスコンストラクション関数を使用して継承
function Parent(name, age) {
this.name = name,
this.age = age,
this.setName = function () {}
}
Parent.prototype.setAge = function () {}
function Child(name, age, price) {
Parent(this, name, age) // : this.Parent(name, age)
/*this.name = name
this.age = age*/
this.price = price
}
var s1 = new Child('Tom', 20, 15000)
この方法は、まず、
Child
を初期化する前に、Child
を初期化します.ここでは、new
に関する知識点に関し、new
の前にthis
をChild.prototype
というオブジェクトに初期化します.ここでは、Function.prototype.call
を使用してParentを呼び出します.実際には、次のようなコードです.
const ChildPrototype = {
Parent: function(name, age) {
//...
}
}
ここではParentで
this
を用いて初期化された属性と方法が得られ,ここではParentプロトタイプチェーンのデータは取得できない.この方法を使用すると、次のようなメリットとデメリットがあります.メリット
call
複数の親オブジェクト)欠点
instanceof
を使用することは、親インスタンスここで使用
Function.prototype.call
はこちらをご覧いただけます組合せ継承(プロトタイプチェーン+サブクラス構築関数)-1
function Parent(name, age) {
this.name = name,
this.age = age,
this.setAge = function () { }
}
Parent.prototype.setAge = function () {
console.log("111")
}
function Child(name, age, price) {
Parent.call(this, name, age)
this.price = price
this.setScore = function () { }
}
Child.prototype = new Parent()
Child.prototype.contructor = Child
Child.prototype.sayHello = function () { }
var s1 = new Child('Tom', 20, 15000)
console.log(s1)
ここではプロトタイプチェーン継承と構造関数の利点を融合させた.しかし、欠点は、サブクラスを作成するときに2回の親クラスを呼び出すコンストラクション関数が呼び出されることです.上記の
Child.prototype.contructor = Child
では、プロトタイプチェーンによる継承修復が必要である.ここでは主に前のいくつかの継承問題を修復します.グループ継承-2
function Parent(name, age) {
this.name = name,
this.age = age,
this.setAge = function () { }
}
Parent.prototype.setAge = function () {
console.log("111")
}
function Child(name, age, price) {
Parent.call(this, name, age)
this.price = price
this.setScore = function () { }
}
Child.prototype = Parent.prototype
Child.prototype.sayHello = function () { }
var s1 = new Child('Tom', 20, 15000)
console.log(s1)
ここでは、子の
prototype
をParent.prototype
に再割り当てすることによって、親のすべてのプロトタイプチェーン上の属性、例えばsetAge
を継承することができ、子の関数宣言では、Parent.call
を通じて親自身の属性と方法を継承することができる.このようにして、2回の呼び出し構造関数の問題を解決することができるが、ここでは、サブクラス構造関数Child.prototype.constructor
が親構造関数によって覆われ、Parent.prototype.construtor
およびChild.prototype.constructor
がいずれもParent.prototype.constructor
を指すという問題もある.グループ継承-3
function Parent(name, age) {
this.name = name,
this.age = age,
this.setAge = function () { }
}
Parent.prototype.setAge = function () {
console.log("111")
}
function Child(name, age, price) {
Parent.call(this, name, age)
this.price = price
this.setScore = function () { }
}
Child.prototype = Object.create(Parent.prototype)
Child.prototype.construct = Child
Child.prototype.sayHello = function () { }
var s1 = new Child('Tom', 20, 15000)
console.log(s1)
ここで、上記との違いは、
Object.create()
を用いてParent.prototype
をChild.prototype.__proto__
に設定することであり、すなわち、現在の構成は以下の図になる.このような方式の継承を通じて、現在では最も完璧な方式であり、以前の多くの問題も解決されている.
ES 6のextendsキーワード
class Parent {
//
constructor(name, age) {
this.name = name
this.age = age
}
//
showName() {
console.log(" ")
console.log(this.name, this.age);
}
}
let p1 = new Parent('kobe', 39)
console.log(p1)
//
class Child extends Parent {
constructor(name, age, salary) {
super(name, age)// super
this.salary = salary
}
showName() {//
console.log(" ")
console.log(this.name, this.age, this.salary);
}
}
let s1 = new Child('wade', 38, 1000000000)
console.log(s1)
s1.showName()
この方式は現在のes 6の方式で、欠点は互換性で、すべてのブラウザがes 6と完璧に互換性があるわけではありません.しかし、他の言語と一致した継承文法が明らかで、分かりやすいです.
実際のJSはプロトタイプチェーンで継承されているので、ここでは最終的に次のコードにコンパイルされます.
これはBabelコンパイルの結果であり,プロトタイプチェーンによって実現されるかを見ることができる.
"use strict";
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
function _instanceof(left, right) { if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) { return right[Symbol.hasInstance](left); } else { return left instanceof right; } }
function _classCallCheck(instance, Constructor) { if (!_instanceof(instance, Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Test = function Test() {
_classCallCheck(this, Test);
};
var Test1 =
/*#__PURE__*/
function (_Test) {
_inherits(Test1, _Test);
function Test1() {
_classCallCheck(this, Test1);
return _possibleConstructorReturn(this, _getPrototypeOf(Test1).apply(this, arguments));
}
return Test1;
}(Test);
次の図を見てください.
ここでコードとコンビネーション継承3は似ていますよ
詳細:
https://www.quora.com/What-is...
https://segmentfault.com/a/11...