JavaScript 継承の機能: 1. 「親クラス」のコンストラクターを呼び出さずに新しいインスタンスを作成できます; 2. 「親クラス」のプロトタイプを変更することで、作成されたすべてのインスタンスを動的に変更できます; 3.オブジェクトのプロトタイプを動的に変更できます。
このチュートリアルの動作環境: Windows7 システム、JavaScript バージョン 1.8.5、Dell G3 コンピューター。
JavaScript は、オブジェクト、モデルとしての関数、および継承としてのプロトタイプに基づくオブジェクト指向開発モデルです。
#JavaScript 継承の役割: #1. 「親クラス」のコンストラクターを呼び出さずに新しいインスタンスを作成できます
2、「親クラス」のプロトタイプを変更して、作成されたすべてのインスタンスを動的に変更します
3. オブジェクトのプロトタイプを動的に変更できます。つまり、親は変更できます
次のJavaScript の型メソッドの定義と、継承を実装するための一般的なパターンを紹介します。
プロトタイプの構築プロトタイプのプロトタイプを直接使用してクラス継承を設計する場合には、2 つの問題があります。
コンストラクタは事前に宣言され、クラス構造の宣言後にプロトタイプの属性が定義されるため、コンストラクタを介してプロトタイプに動的にパラメータを渡すことはできません。このように、インスタンス化されたオブジェクトはすべて同じように見え、個性がありません。プロトタイプのプロパティ値を変更すると、すべてのインスタンスが影響を受けます。
プロトタイプ属性の値が参照型データの場合、1 つのオブジェクト インスタンスで属性値を変更すると、すべてのインスタンスに影響します。
例 1
Book タイプを定義してインスタンス化するだけです。
function Book () {}; //声明构造函数 Book.prototype.o = {x : 1, y : 2}; //构造函数的原型属性o是一个对象 var book1 = new Book (); //实例化对象book1 var book2 = new Book (); //实例化对象book2 console.log(book1.o.x); //返回1 console.log(book2.o.x); //返回1 book2.o.x = 3; //修改实例化对象book2中的属性x的值 console.log(book1.o.x); //返回3 console.log(book2.o.x); //返回3
プロトタイプ属性 o は参照値であるため、すべてのインスタンスの属性 o の値は同じオブジェクトへの参照になります。o の値が変更されると、すべてのインスタンスに影響します。
コンストラクション プロトタイプは、プロトタイプ パターンを解決するために生まれたハイブリッド デザイン パターンであり、上記の問題を回避するために、コンストラクター パターンとプロトタイプ パターンを混合します。
実装方法: 相互に影響を与える可能性のあるプロトタイププロパティや動的にパラメータを渡したいプロパティは、コンストラクタパターンを使用して独立して設計できます。個別に設計する必要がなく、共通の特性を持つメソッドや属性については、プロトタイプパターンを使用して設計できます。
例 2
上記の設計原則に従い、2 つのプロパティをコンストラクター パターンに設計します。この設計メソッドはプロトタイプ パターンです。
function Book (title, pages) { //构造函数模式设计 this.title = title; this.pages = pages; } Book.prototype.what = function () { //原型模式设计 console.log(this.title + this.pages); }; var book1 = new Book("JavaScript 程序设计", 160); var book2 = new Book("C语言程序设计", 240); console.log(book1.title); console.log(book2.title);
構築されたプロトタイプ パターンは、ECMAScript でクラスを定義するための推奨標準です。一般に、コンストラクター パターンを使用してすべてのプロパティを定義し、プロトタイプ パターンを使用してすべてのメソッドを定義することをお勧めします。この方法では、すべてのメソッドが 1 回だけ作成され、各インスタンスは必要に応じてプロパティ値を設定できます。これは最も広く使用されているデザイン パターンでもあります。
動的プロトタイプオブジェクト指向設計原則によれば、型のすべてのメンバーはクラス構造にカプセル化される必要があります。例:
function Book (title, pages) { //构造函数模式设计 this.title = title; this.pages = pages; Book.prototype.what = function () { //原型模式设计,位于类的内部 console.log(this.title + this.pages); }; }
しかし、インスタンス化されるたびに、クラス Book に含まれるプロトタイプ メソッドが繰り返し作成され、大量のプロトタイプ メソッドが生成され、システム リソースが無駄に消費されます。 if を使用して、プロトタイプ メソッドが存在するかどうかを判断できます。存在する場合、メソッドは作成されません。存在しない場合、メソッドは作成されます。
function Book (title, pages) { this.title = title; this.pages = pages; if (typeof Book.isLock == "undefined") { //创建原型方法的锁,如果不存在则创建 Book.prototype.what = function () { console.log(this.title + this.pages); }; Book.isLock = true; //创建原型方法后,把锁锁上,避免重复创建 } } var book1 = new Book("JavaScript 程序设计", 160); var book2 = new Book("C语言程序设计", 240); console.log(book1.title); console.log(book2.title);
typeof Book.isLock 式は属性値の型を検出できます。未定義の文字列が返された場合、属性値は存在せず、プロトタイプ メソッドが作成されていないことを示し、この属性を設定するには、プロトタイプ メソッドを使用します。値は true なので、プロトタイプ メソッドを繰り返し作成する必要はありません。プロトタイプはオブジェクト インスタンスではなくクラス自体に属しているため、ここではクラス名 Book が使用されています。
動的プロトタイプ モードと構築プロトタイプ モードはパフォーマンスが同等であり、ユーザーは自由に選択できますが、構築プロトタイプ モードの方が広く使用されています。
ファクトリ パターンファクトリ パターンは型を定義する最も基本的な方法であり、JavaScript で最も一般的に使用される開発パターンでもあります。オブジェクトのインスタンス化を関数にカプセル化し、その関数を呼び出して、インスタンス オブジェクトの迅速なバッチ生成を実現します。
例 1
次の例では、車のタイプを設計します。これには、車の色、駆動輪の数、100 キロメートルごとの燃料消費量の 3 つの属性が含まれており、また、車の色。
function Car (color, drive, oil) { //汽车类 var _car = new Object(); //临时对象 _car.color = color; //初始化颜色 _car.drive = drive; //初始化驱动轮数 _car.oil = oil; //初始化百公里油耗 _car.showColor = function () { //方法,提示汽车颜色 console.log(this.color); }; return _car; //返回实例 } var car1 = Car("red", 4, 8); var car2 = Car("blue", 2, 6); car1.showColor(); //输出“red” car2.showColor(); //输出“blue”
上記のコードは、単純なファクトリ パターン タイプです。Car クラスを使用すると、複数の車のインスタンスをすばやく作成できます。それらの構造は同じですが、属性が異なります。異なる色、数を初期化できます。駆動輪と100kmあたりの燃料消費量。
例 2
型において、メソッドは、初期化パラメータに基づいて特定のタスクを完了できる動作または操作であり、共通の特性を持っています。したがって、メソッドを Car() 関数の外側に配置して、インスタンス化されるたびに関数を作成することを避け、各インスタンスが同じ関数を共有できるようにすることを検討できます。
function showColor () { //公共方法,提示汽车颜色 console.log(this.color); }; function Car (color, drive, oil) { //汽车类 var _car = new Object(); //临时对象 _car.color = color; //初始化颜色 _car.drive = drive; //初始化驱动轮数 _car.oil = oil; //初始化百公里油耗 _car.showColor = showColor; //引用外部函数 return _car; //返回实例 }
上記の書き換えられたコードでは、関数 showColor() が関数 Car() の前に定義されています。 Car() 内で外部の showColor() 関数を参照することにより、インスタンス化されるたびに新しい関数を作成する必要がなくなります。機能的には、これにより関数を繰り返し作成する問題は解決されますが、意味的には、この関数はオブジェクト メソッドとは異なります。
#クラス継承
クラス継承の設計方法: サブクラスで親クラスのコンストラクターを呼び出します。
在 JavaScript 中实现类继承,需要注意以下 3 个技术问题。
在子类中,使用 apply 调用父类,把子类构造函数的参数传递给父类父类构造函数。让子类继承父类的私有属性,即 Parent.apply(this, arguments); 代码行。
在父类和子类之间建立原型链,即 Sub.prototype = new Parent(); 代码行。通过这种方式保证父类和子类是原型链上的上下级关系,即子类的 prototype 指向父类的一个实例。
恢复子类的原型对象的构造函数,即 Sub.prototype.constructor=Sub;语句行。当改动 prototype 原型时,就会破坏原来的 constructor 指针,所以必须重置 constructor。
示例1
下面示例演示了一个三重继承的案例,包括基类、父类和子类,它们逐级继承。
//基类Base function Base (x) { //构造函数Base this.get = function () { //私有方法,获取参数值 return x; } } Base.prototype.has = function () { //原型方法,判断get()方法返回值是否为0 return ! (this.get() == 0); } //父类Parent function Parent () { //构造函数Parent var a = []; //私有数组a a = Array.apply(a, arguments); //把参数转换为数组 Base.call(this, a.length); //调用Base类,并把参数数组长度传递给它 this.add = function () { //私有方法,把参数数组补加到数组a中并返回 return a.push.apply(a, arguments) } this.geta = function () { //私有方法,返回数组a return a; } } Parent.prototype = new Base(); //设置Parent原型为Base的实例,建立原型链 Parent.prototype.constructor = Parent; //恢复Parent类原型对象的构造器 Parent.prototype.str = function (){ //原型方法,把数组转换为字符串并返回 return this.geta().toString(); } //子类Sub function Sub () { //构造函数 Parent.apply(this, arguments); //调用Parent类,并把参数数组长度传递给它 this.sort = function () { //私有方法,以字符顺序对数组进行排序 var a = this.geta(); //获取数组的值 a.sort.apply(a, arguments); //调用数组排序方法 sort()对数组进行排序 } } Sub.prototype = new Parent(); //设置Sub原型为Parent实例,建立原型链 Sub.prototype.constructor = Sub; //恢复Sub类原型对象的构造器 //父类Parent的实例继承类Base的成员 var parent = new Parent (1, 2, 3, 4); //实例化Parent类 console.log(parent.get()); //返回4,调用Base类的方法get() console.log(parent.has()); //返回true,调用Base类的方法has() //子类Sub的实例继承类Parent和类Base的成员 var sub = new Sub (30, 10, 20, 40); //实例化Sub类 sub.add(6, 5); //调用Parent类方法add(),补加数组 console.log(sub.geta()); //返回数组30,10,20,40,6,5 sub.sort(); //排序数组 console.log(sub.geta()); //返回数组10,20,30,40,5,6 console.log(sub.get()); //返回4,调用Base类的方法get() console.log(sub.has()); //返回true,调用Base类的方法has() console.log(sub.str()); //返回10,20,30,40,5,6
【设计思路】
设计子类 Sub 继承父类 Parent,而父类 Parent 又继承基类 Base。Base、Parent、Sub 三个类之间的继承关系是通过在子类中调用的构造函数来维护的。
例如,在 Sub 类中,Parent.apply(this, arguments); 能够在子类中调用父类,并把子类的参数传递给父类,从而使子类拥有父类的所有属性。
同理,在父类中,Base.call(this, a.length); 把父类的参数长度作为值传递给基类,并进行调用,从而实现父类拥有基类的所有成员。
从继承关系上看,父类继承了基类的私有方法 get(),为了确保能够继承基类的原型方法,还需要为它们建立原型链,从而实现原型对象的继承关系,方法是添加语句行 Parent.prototype=new Base();。
同理,在子类中添加语句 Sub.prototype=new Parent();,这样通过原型链就可以把基类、父类和子类串连在一起,从而实现子类能够继承父类属性,还可以继承基类的属性。
示例2
下面尝试把类继承模式封装起来,以便规范代码应用。
function extend (Sub, Sup) { //类继承封装函数 var F = function () {}; //定义一个空函数 F.prototype = Sup.prototype; //设置空函数的原型为父类的原型 Sub.prototype = new F (); //实例化空函数,并把父类原型引用传给给子类 Sub.prototype.constructor = Sub; //恢复子类原型的构造器为子类自身 Sub.sup = Sup.prototype; //在子类定义一个私有属性存储父类原型 //检测父类原型构造器是否为自身 if (Sup.prototype.constructor == Object.prototype.constructor) { Sup.prototype.constructor = Sup; //类继承封装函数 } }
【操作步骤】
1) 定义一个封装函数。设计入口为子类和父类对象,函数功能是子类能够继承父类的所有原型成员,不涉及出口。
function extend (Sub, Sup) { //类继承封装函数 //其中参数Sub表示子类,Sup表示父类 }
2) 在函数体内,首先定义一个空函数 F,用来实现功能中转。设计它的原型为父类的原型,然后把空函数的实例传递给子类的原型,这样就避免了直接实例化父类可能带来的系统负荷。因为在实际开发中,父类的规模可能会很大,如果实例化,会占用大量内存。
3) 恢复子类原型的构造器为子类自己。同时,检测父类原型构造器是否与 Object 的原型构造器发生耦合。如果是,则恢复它的构造器为父类自身。
下面定义两个类,尝试把它们绑定为继承关系。
function A (x) { //构造函数A this.x = x; //私有属性x this.get = function () { //私有方法get() return this.x; } } A.prototype.add = function () { //原型方法add() return this.x + this.x; } A.prototype.mul = function () { //原型方法mul() return this.x * this.x; } function B (x) { //构造函数B A.call (this.x); //在函数体内调用构造函数A,实现内部数据绑定 } extend (B, A); //调用封装函数,把A和B的原型捆绑在一起 var f = new B (5); //实例化类B console.log(f.get()); //继承类A的方法get(),返回5 console.log(f.add()); //继承类A的方法add(),返回10 console.log(f.mul()); //继承类A的方法mul(),返回25
在函数类封装函数中,有这么一句 Sub.sup=Sup.prototype;,在上面代码中没有被利用,那么它有什么作用呢?为了解答这个问题,先看下面的代码。
extend (B, A); B.prototype.add = function () { //为B类定义一个原型方法 return this.x + "" + this.x; }
上面的代码是在调用封装函数之后,再为 B 类定义了一个原型方法,该方法名与基类中原型方法 add() 同名,但是功能不同。如果此时测试程序,会发现子类 B 定义的原型方法 add() 将会覆盖父类 A 的原型方法 add()。
console.log(f.add()); //返回字符串55,而不是数值10
如果在 B 类的原型方法 add() 中调用父类的原型方法 add(),避免代码耦合现象发生。
B.prototype.add = function () { //定义子类B的原型方法add() return B.sup.add.call(this); //在函数内部调用父类方法add() }
【相关推荐:javascript学习教程】
以上がJavaScriptの継承はどのような用途に使われるのでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

IDセレクターを使用することは、CSSでは本質的に悪くはありませんが、注意して使用する必要があります。 1)IDセレクターは、一意の要素またはJavaScriptフックに適しています。 2)一般的なスタイルの場合、クラスセレクターはより柔軟で保守可能であるため、使用する必要があります。 IDとクラスの使用のバランスをとることにより、より堅牢で効率的なCSSアーキテクチャを実装できます。

HTML5'SGOALSIN2024FOCUSONREFINIMINGANDOPTIMIZATION、notnewfeatures.1)強化された拡張性と拡張効率化されたレンダリング.2)

html5aimed toemprovewebdevelymentinfourkeyareas:1)multimediasupport、2)セマンティクス構造、3)フォームキャピリティ、および4)offlineandstorageoptions.1)html5introduededelements、simplifiedediaembedingemencemanteddim.2)

idsは、Javascripthooksを使用しているので、whileclasseSarebetterforstyling.1)useclassess forStylingtoEriousEREUSERESERESERESPICITYISSUES.2)USEIDSSFORIDSSSCRIPTHOOKSTOUNIQUELYIEDIENEMENTS.3)3)回避策を避けてください

classSelectorEctorSareverSatileAndReusable、whiledseLectorSareUniqueandspecific.1)useclassselectors(notedby。)forstylingMultipleElementswithsharedCharacteristics.2)useidselectors(notedby#)forstylinguniqueeletementonapage.classselectorectorotorsoffermoreflexibili

idsareuniqueIdentifiersforsingleelements、whileclassesstylemultipleements.1)useidsforuniqueelementsandjavascripthooks.2)useclasses forReusable、flexiblestylingacrossmultipletements。

クラスのみのセレクターを使用すると、コードの再利用性と保守性が向上しますが、クラス名と優先順位の管理が必要です。 1.再利用性と柔軟性を向上させる、2。複数のクラスを組み合わせて複雑なスタイルを作成する3。長いクラス名と優先順位につながる可能性があります。4。パフォーマンスへの影響は小さい、5。簡潔な命名や使用規則などのベストプラクティスに従ってください。

IDおよびクラスセレクターは、それぞれ一意でマルチエレメントスタイルの設定にCSSで使用されます。 1. IDセレクター(#)は、特定のナビゲーションメニューなどの単一の要素に適しています。 2.クラスセレクター(。)は、統一ボタンスタイルなどの複数の要素に使用されます。 IDは注意して使用し、過度の特異性を避け、スタイルの再利用性と柔軟性を向上させるためにクラスに優先順位を付ける必要があります。


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

WebStorm Mac版
便利なJavaScript開発ツール

EditPlus 中国語クラック版
サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

SecLists
SecLists は、セキュリティ テスターの究極の相棒です。これは、セキュリティ評価中に頻繁に使用されるさまざまな種類のリストを 1 か所にまとめたものです。 SecLists は、セキュリティ テスターが必要とする可能性のあるすべてのリストを便利に提供することで、セキュリティ テストをより効率的かつ生産的にするのに役立ちます。リストの種類には、ユーザー名、パスワード、URL、ファジング ペイロード、機密データ パターン、Web シェルなどが含まれます。テスターはこのリポジトリを新しいテスト マシンにプルするだけで、必要なあらゆる種類のリストにアクセスできるようになります。

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

AtomエディタMac版ダウンロード
最も人気のあるオープンソースエディター
