ホームページ ウェブフロントエンド jsチュートリアル JavaScriptのプロトタイプ継承に関する基礎学習チュートリアル_基礎知識

JavaScriptのプロトタイプ継承に関する基礎学習チュートリアル_基礎知識

May 16, 2016 pm 03:01 PM
javascript プロトタイプ 継承する

ほとんどのプログラミング言語にはクラスとオブジェクトがあり、あるクラスは他のクラスを継承できます。
JavaScript では、継承はプロトタイプベースです。つまり、JavaScript にはクラスがなく、代わりに 1 つのオブジェクトが別のオブジェクトを継承します。 :)

1. 継承、プロト
JavaScript では、ウサギのオブジェクトが別のオブジェクトの動物を継承すると、ウサギのオブジェクトに特別な属性が存在することになります: Rabbit.__proto__ = Animal;
Rabbit オブジェクトにアクセスするときに、インタープリタが Rabbit で属性を見つけられない場合、__proto__ チェーンに従い、animal オブジェクトで
を探します。 チェストナットの __proto__ 属性は Chrome と FireFox でのみアクセス可能です。チェストナットを参照してください:

var animal = { eats: true }
var rabbit = { jumps: true }

rabbit.__proto__ = animal // inherit

alert(rabbit.eats) // true

ログイン後にコピー

eats 属性は、animal オブジェクトからアクセスされます。
プロパティが Rabbit オブジェクトで見つかった場合、proto プロパティはチェックされません。
別の例として、サブクラスにも Eats 属性がある場合、親クラスの属性にはアクセスできません。

var animal = { eats: true }
var fedUpRabbit = { eats: false}

fedUpRabbit.__proto__ = animal 

alert(fedUpRabbit.eats) // false

ログイン後にコピー

animal で関数を追加することもでき、rabbit でアクセスすることもできます。

var animal = {
 eat: function() {
  alert( "I'm full" )
  this.full = true
 }
}


var rabbit = {
 jump: function() { /* something */ }
}

rabbit.__proto__ = animal 

ログイン後にコピー

(1) Rabbit.eat():
Rabbit.eat() 関数は次の 2 つのステップで実行されます:
まず、インタープリタは、rabbit.eat を探します。rabbit には Eat 関数がないため、rabbit.__proto__ を検索し、animal で見つけます。
この関数は this = Rabbit で実行されます。 this 値は __proto__ 属性とはまったく関係がありません。
したがって、rabbit では this.full = true:
ここでどのような新しい発見があるかを見てみましょう。オブジェクトは親クラスの関数を呼び出しますが、これは依然としてオブジェクト自体を指します。
__proto__ によって参照されるオブジェクトはプロトタイプと呼ばれ、動物はウサギのプロトタイプです (翻訳者注: これは、ウサギの __proto__ 属性が動物のプロトタイプ属性を参照しているためです)
(2) 書き込み時ではなく、読み取り時に検索
this.prop などのオブジェクトを読み取るとき、インタプリタはそのプロトタイプ内でプロパティを探します。
this.prop = value などのプロパティ値を設定する場合、それを探す必要はありません。プロパティ (prop) はオブジェクト (ここでは this) に直接追加されます。 delete obj.prop も同様で、オブジェクト自体のプロパティのみを削除し、プロトタイプ内のプロパティはそのまま残ります。
(3) プロト
について ガイドをお読みの場合、ここで __proto__ と呼ぶものは、ガイド内では [[プロトタイプ]] として表されます。プロトタイプと呼ばれる別の属性があるため、二重括弧は重要です。

2. Object.create、Object.getPrototypeOf
__proto__ は Chrome/FireFox によって提供される非標準属性であり、他のブラウザでは表示されません。
Opera (IE > 9) を除くすべての最新ブラウザは、プロトタイプの問題を処理するための 2 つの標準関数をサポートしています:

Object.ceate(prop[,props])
ログイン後にコピー

指定されたプロトで空のオブジェクトを作成します:

var animal = { eats: true }

rabbit = Object.create(animal)

alert(rabbit.eats) // true

ログイン後にコピー

上記のコードは空のウサギのオブジェクトを作成し、プロトタイプをanimalに設定します
ウサギ オブジェクトが作成されたら、それに属性を追加できます:

var animal = { eats: true }

rabbit = Object.create(animal)
rabbit.jumps = true

ログイン後にコピー

Object.creat 関数の 2 番目のパラメーター props はオプションであり、新しいオブジェクトと同様にプロパティを設定できます。関係の継承のため、ここでは省略します。
(1) Object.getPrototypeOf(obj)
obj.__proto__ の値を返します。この関数は標準であり、__proto__ 属性に直接アクセスできないブラウザで使用できます。

var animal = {
 eats: true
}

rabbit = Object.create(animal)

alert( Object.getPrototypeOf(rabbit) === animal ) // true

ログイン後にコピー

最新のブラウザでは、__proto__ 属性値を読み取ることはできますが、設定することはできません。

3. プロトタイプ
__proto__ 属性を設定するには、コンストラクター関数を使用する、ブラウザーを超えた優れた方法がいくつかあります。覚えて!どの関数も new キーワードを使用してオブジェクトを作成します。
栗:

function Rabbit(name) {
 this.name = name
}

var rabbit = new Rabbit('John')

alert(rabbit.name) // John

ログイン後にコピー

新しいオペレーションは、プロトタイプの属性を Rabbit オブジェクトの __proto__ 属性に設定します。
たとえば、新しい Rabbit オブジェクトと Rabbit がanimal から継承する様子を見てみましょう。

var animal = { eats: true }

function Rabbit(name) {
 this.name = name
}

Rabbit.prototype = animal

var rabbit = new Rabbit('John')

alert( rabbit.eats ) // true, because rabbit.__proto__ == animal

ログイン後にコピー

Rabbit.prototype = Animal リテラルの意味: 新しい Rabbit によって作成されたすべてのオブジェクトに対して __proto__ = Animal

を設定します

4. クロスブラウザー Object.create(proto)
Object.create(prop) 関数は、特定のオブジェクトから直接継承できるため、強力です。次のコードでシミュレートできます:

function inherit(proto) {
 function F() {}
 F.prototype = proto
 return new F
}
ログイン後にコピー

inherit(animal) は Object.create(animal) と完全に同等で、空のオブジェクトと object.__proto__ = anime を返します。
栗:

var animal = { eats: true }

var rabbit = inherit(animal)

alert(rabbit.eats) // true
alert(rabbit.hasOwnProperty('eats')) // false, from prototype

ログイン後にコピー

それがどのように機能するかを見てみましょう:

function inherit(proto) {
 function F() {}   // (1)
 F.prototype = proto // (2)
 return new F()   // (3)
}
ログイン後にコピー

(1) 创建了一个新函数,函数没有向this设置任何属性,以此`new F` 会创建一个空对象。
(2) `F.prototype`被设置为proto
(3) `new` F创建了一个空对象,对象的`__proto__ = F.prototype`
(4) Bingo! 我们得到了一个继承`proto`的空对象
这个函数广泛适用于各种库和框架之中。
你的函数接受了一个带有options 的对象

/* options contains menu settings: width, height etc */
function Menu(options) {
 // ...
}
你想设置某些options
function Menu(options) {
 options.width = options.width || 300 // set default value
 // ...
}
ログイン後にコピー

。。。但是改变参数值可能会产生一些错误的结果,因为options可能会在外部代码中使用。一个解决办法就是克隆options对象,复制所有的属性到一个新的对象中,在新对象中修改,
怎样用继承来解决这个问题呢? P.S. options可以添加设设置,但是不能被删除。
Solution
你可以继承options,并且在它的子类的中修改或者添加新的属性。

function inherit(proto) {
 function F() {}
 F.prototype = proto
 return new F
}

function Menu(options) {
 var opts = inherit(options)
 opts.width = opts.width || 300
 // ...
}

ログイン後にコピー

所有的操作只在子对象中有效,当Menu方法结束时,外部代码仍然可以使用没有修改的过的options对象。delete操作在这里非常重要,如果width是一个prototype中的属性,delete opts.width不会产生任何作用

5. hasOwnProperty
所有的对象都有hasOwnProperty函数,它可以用来检测一个属性是否对象自身还是属于原型
一个栗子:

function Rabbit(name) {
 this.name = name
}

Rabbit.prototype = { eats: true }

var rabbit = new Rabbit('John')

alert( rabbit.hasOwnProperty('eats') ) // false, in prototype

alert( rabbit.hasOwnProperty('name') ) // true, in object

ログイン後にコピー

6. Looping with/without inherited properties
for..in循环输出一个对象的所有属性,包括自身的和原型的。

function Rabbit(name) {
 this.name = name
}

Rabbit.prototype = { eats: true }

var rabbit = new Rabbit('John')

for(var p in rabbit) {
 alert (p + " = " + rabbit[p]) // outputs both "name" and "eats"
}

ログイン後にコピー

用hasOwnProperty可以过滤得到属于对象自己的属性:

function Rabbit(name) {
 this.name = name
}

Rabbit.prototype = { eats: true }

var rabbit = new Rabbit('John')

for(var p in rabbit) {
 if (!rabbit.hasOwnProperty(p)) continue // filter out "eats"
 alert (p + " = " + rabbit[p]) // outputs only "name"
}

ログイン後にコピー

7. Summary
JavaScript是通过一个特殊的属性proto来实现继承的
当访问一个对象的属性时,如果解释器不能在对象中找到,它就会去对象的原型中继续寻找 对函数属性来说,this指向这个对象,而不是它的原型。
赋值obj.prop = value, 删除delete obj.prop
管理proto:
Chrome和FireFox可以直接访问对象的__proto__属性,大多数现代浏览器支持用Object.getPrototypeOf(obj)只读访问。
Object.create(proto) 可以用给定的proto生成空的子对象,或者通过如下代码达到相同的功能:

function inherit(proto) {
   function F() {}   
   F.prototype = proto
   return new F()  
  }
ログイン後にコピー

其他方法:
for..in循环输出一个对象的所有属性(包括自身的和原型的)和对象的原型链。
如果一个属性prop属于对象obj那么obj.hasOwnProperty(prop)返回true,否则返回false。

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

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

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

C++関数継承の詳しい解説:継承で「基底クラスポインタ」と「派生クラスポインタ」を使うには? C++関数継承の詳しい解説:継承で「基底クラスポインタ」と「派生クラスポインタ」を使うには? May 01, 2024 pm 10:27 PM

関数の継承では、「基底クラス ポインター」と「派生クラス ポインター」を使用して継承メカニズムを理解します。基底クラス ポインターが派生クラス オブジェクトを指す場合、上方変換が実行され、基底クラスのメンバーのみにアクセスされます。派生クラス ポインターが基本クラス オブジェクトを指す場合、下向きキャストが実行される (安全ではない) ため、注意して使用する必要があります。

継承とポリモーフィズムは C++ のクラス結合にどのような影響を与えますか? 継承とポリモーフィズムは C++ のクラス結合にどのような影響を与えますか? Jun 05, 2024 pm 02:33 PM

継承とポリモーフィズムはクラスの結合に影響します。派生クラスは基本クラスに依存するため、継承により結合が増加します。ポリモーフィズムにより、オブジェクトは仮想関数と基本クラス ポインターを通じて一貫した方法でメッセージに応答できるため、結合が軽減されます。ベスト プラクティスには、継承を控えめに使用すること、パブリック インターフェイスを定義すること、基本クラスへのデータ メンバーの追加を回避すること、依存関係の注入を通じてクラスを分離することが含まれます。ポリモーフィズムと依存性注入を使用して銀行口座アプリケーションの結合を軽減する方法を示す実践的な例。

C++ 関数の継承の詳細な説明: 継承のエラーをデバッグするには? C++ 関数の継承の詳細な説明: 継承のエラーをデバッグするには? May 02, 2024 am 09:54 AM

継承エラーのデバッグのヒント: 正しい継承関係を確認します。デバッガーを使用してコードをステップ実行し、変数値を調べます。仮想修飾子を正しく使用してください。隠れた相続によって引き起こされる相続ダイアモンド問題を調べてください。抽象クラスに実装されていない純粋仮想関数がないか確認します。

C++ 関数の継承の詳細な説明: 継承における 'is-a' と 'has-a' の関係を理解するには? C++ 関数の継承の詳細な説明: 継承における 'is-a' と 'has-a' の関係を理解するには? May 02, 2024 am 08:18 AM

C++の関数継承を詳しく解説:「is-a」と「has-a」の関係をマスターしよう 関数継承とは?関数の継承は、派生クラスで定義されたメソッドを基本クラスで定義されたメソッドに関連付ける C++ の手法です。これにより、派生クラスが基本クラスのメソッドにアクセスしてオーバーライドできるようになり、基本クラスの機能が拡張されます。 「is-a」および「has-a」関係 関数継承では、「is-a」関係は、派生クラスが基本クラスのサブタイプであること、つまり、派生クラスが基本クラスの特性と動作を「継承」することを意味します。基本クラス。 「has-a」関係は、派生クラスに基本クラス オブジェクトへの参照またはポインターが含まれていること、つまり、派生クラスが基本クラス オブジェクトを「所有」していることを意味します。構文関数継承を実装する方法の構文は次のとおりです: classDerivedClass:pu

C++ 関数の継承の説明: 継承を使用すべきでないのはどのような場合ですか? C++ 関数の継承の説明: 継承を使用すべきでないのはどのような場合ですか? May 04, 2024 pm 12:18 PM

C++ 関数の継承は、次の状況では使用しないでください。 派生クラスが異なる実装を必要とする場合、異なる実装を持つ新しい関数を作成する必要があります。派生クラスが関数を必要としない場合は、空のクラスとして宣言するか、プライベートの未実装の基本クラス メンバー関数を使用して関数の継承を無効にする必要があります。関数が継承を必要としない場合は、コードの再利用を実現するために他のメカニズム (テンプレートなど) を使用する必要があります。

原神バージョン 4.4 の新しいマップの紹介 原神バージョン 4.4 の新しいマップの紹介 Jan 31, 2024 pm 06:36 PM

原神 バージョン 4.4 の新しいマップの紹介. 皆さん、原神 4.4 バージョンでは、立月のシー ランタン フェスティバルも始まりました. 同時に、バージョン 4.4 では神羽渓谷と呼ばれる新しいマップ エリアが開始されます。提供された情報によると、沈雨谷は実際には喬営村の一部ですが、プレイヤーはそれを沈雨谷と呼ぶことに慣れています。それでは、新しい地図をご紹介します。原神バージョン 4.4 の新マップのご紹介です。バージョン 4.4 では、立月北部に「陳兪渓谷・上谷」、「陳兪渓谷・南嶺」、「来新山」がオープンします。谷・上谷」。 ※魔神クエスト・第3幕「ドラゴンと自由の歌」プロローグをクリアすると、テレポートアンカーポイントが自動で解放されます。 2. 喬営荘 暖かい春風が再び陳嶼の山野を撫でるとき、香りのよい

「PHP によるオブジェクト指向プログラミング入門: 概念から実践まで」 「PHP によるオブジェクト指向プログラミング入門: 概念から実践まで」 Feb 25, 2024 pm 09:04 PM

オブジェクト指向プログラミングとは何ですか?オブジェクト指向プログラミング (OOP) は、現実世界のエンティティをクラスに抽象化し、オブジェクトを使用してこれらのエンティティを表すプログラミング パラダイムです。クラスはオブジェクトのプロパティと動作を定義し、オブジェクトはクラスをインスタンス化します。 OOP の主な利点は、コードの理解、保守、再利用が容易になることです。 OOP の基本概念 OOP の主な概念には、クラス、オブジェクト、プロパティ、メソッドが含まれます。クラスはオブジェクトの設計図であり、オブジェクトのプロパティと動作を定義します。オブジェクトはクラスのインスタンスであり、クラスのすべてのプロパティと動作を備えています。プロパティは、データを保存できるオブジェクトの特性です。メソッドは、オブジェクトのデータを操作できるオブジェクトの関数です。 OOP の利点 OOP の主な利点は次のとおりです。 再利用性: OOP はコードをより高度なものにすることができます。

Java インターフェイスと抽象クラス: プログラミング天国への道 Java インターフェイスと抽象クラス: プログラミング天国への道 Mar 04, 2024 am 09:13 AM

インターフェイス: 実装のないコントラクト インターフェイスは、Java でメソッド シグネチャのセットを定義しますが、具体的な実装は提供しません。これは、インターフェイスを実装するクラスに、その指定されたメソッドを強制的に実装するコントラクトとして機能します。インターフェイス内のメソッドは抽象メソッドであり、メソッド本体はありません。コード例: publicinterfaceAnimal{voideat();voidsleep();} 抽象クラス: 部分的に実装されたブループリント 抽象クラスは、そのサブクラスによって継承できる部分的な実装を提供する親クラスです。インターフェイスとは異なり、抽象クラスには具体的な実装と抽象メソッドを含めることができます。抽象メソッドは、abstract キーワードを使用して宣言され、サブクラスによってオーバーライドされる必要があります。コード例: publicabstractcla

See all articles