JavaScript プロトタイプの詳細

JavaScript プロトタイプの詳細

1. 概要

1.1 プロトタイプとは何ですか?

JavaScriptでは、関数はプロパティとメソッドを含むFunction型のオブジェクトです。プロトタイプは Function 型オブジェクトのプロパティです。

prototype プロパティは関数定義に含まれており、その初期値は空のオブジェクトです。 JavaScript では、関数に対して定義されたプリミティブ型はないため、プロトタイプは任意の型にすることができます。

プロトタイプは、オブジェクトの共有プロパティとメソッドを保存するために使用されます。プロトタイプのプロパティとメソッドは、関数自体のプロパティとメソッドには影響しません。

サンプルコードの検証は次のとおりです。

関数fun() {
  console.log('関数プロトタイプ')
}
console.log(fun.prototype) // {}

fun.prototypeも空のオブジェクトを返しますが、これはObject.prototypeにプロパティやメソッドがないことを意味するものではありません。これらのプロパティとメソッドは列挙可能ではありません。サンプル コードは次のとおりです。

関数fun() {
  console.log('関数プロトタイプ')
}

console.log(fun.prototype) // {}
// Object.getOwnPropertyNames() を介してすべてのプロパティを取得します console.log(Object.getOwnPropertyNames(fun.prototype)) // [ 'constructor' ]

このうち、コンストラクター属性はコンストラクターの参照を指します。コードは次のようになります。

// コンストラクタープロパティ console.log(fun.prototype.constructor) // [関数: fun]

console.log(fun.prototype.constructor === fun) // true

1.2 プロトタイプを入手する

プロトタイプの概念と機能を理解した後、プロトタイプを操作する前に取得する必要があります。 JavaScriptでプロトタイプを取得するには、以下に示すように 2 つの方法があります。

コンストラクターのprototypeプロパティを通じて。

Object.getPrototypeOf(obj)メソッドを通じて。

2 つの違いは、コンストラクターの prototype プロパティは通常コンストラクターと組み合わせてのみ使用されるのに対し、Object.getPrototypeOf(obj) メソッドは通常、コンストラクターによってインスタンス化されたオブジェクトのプロトタイプを取得するためのメソッドである点です。

サンプルコードは次のとおりです。

// コンストラクタ関数 Person(name) {
  this.name = 名前
}

// コンストラクタのプロトタイプを指す var p1 = Person.prototype

var person = new Person('Yiwan Zhou')

// コンストラクタのプロトタイプを指す var p2 = Object.getPrototypeOf(person)

console.log(p1 === p2) // 真

プロトタイプ自体もオブジェクトなので、プロトタイプを入手したら、それをオブジェクトのように操作することができます。

2. プロトタイプのプロパティ

JavaScriptでは、関数自体もメソッドとプロパティを含むオブジェクトです。次に、関数オブジェクトの別のプロパティであるプロトタイプについて学習します。このプロパティの初期値は空のオブジェクトです。

2.1 プロトタイプを使用してプロパティとメソッドを追加します。

オブジェクトにプロパティとメソッドを追加する別の方法は、プロトタイプを通じて追加することです。プロトタイプ プロパティとプロトタイプ メソッドをコンストラクターに追加すると、コンストラクターによって新しく作成されたすべてのオブジェクトがプロパティとメソッドを共有します。

PS:いわゆるプロトタイプ プロパティまたはプロトタイプ メソッドは、プロトタイプを通じて追加されるプロパティまたはメソッドです。

プロパティとメソッドを追加する方法はいくつかあります。

属性やメソッドを直接追加する

Object.defineProperty()メソッドを使用してプロパティまたはメソッドを追加します。この方法は最初の方法よりも安全です。

プロトタイプにオブジェクトを直接追加します。

サンプルコードは次のとおりです。

//コンストラクタ関数 Fun() {}
// コンストラクターにプロパティとメソッドを直接追加します Fun.prototype.str = 'This is a string'
Fun.prototype.fn = 関数(){
  console.log('これはメソッドです')
}
//defineProperty を通じてプロパティまたはメソッドを追加します Object.defineProperty(Fun.prototype, 'MyFun', {
  値: 関数 () {
    console.log('これはMyFunです')
  },
})
//テスト console.log(Fun.prototype.str)
Fun.prototype.fn()
Fun.prototype.MyFun()
var fun = 新しい Fun()
楽しいMyFun()
// 以前のプロトタイプをカバーするオブジェクトを直接定義する Fun.prototype = {
  名前:「周の一杯」
  楽しい: 関数() {
    console.log('これは関数です')
  },
}
楽しいプロトタイプ()
var fun = 新しい Fun()
楽しい。楽しい()

2.2 プロトタイププロパティとプロトタイプメソッドへのアクセス

プロトタイプの最も重要な点は、そのリアルタイム性です。 JavaScript のほぼすべてのオブジェクトは参照によって渡されるため、作成する新しいオブジェクト エンティティごとにプロトタイプの独自のコピーは保持されません。つまり、 prototypeプロパティはいつでも変更でき、コンストラクターを通じて作成されたプロパティとメソッドを含め、同じコンストラクターによって作成されたすべてのオブジェクトのプロトタイプ プロパティも同時に変更されます。

上記のコードを引き続き使用して、プロトタイプに新しいメソッドを追加して呼び出します。サンプル コードは次のとおりです。

Fun.prototype.fn = 関数(){
  console.log('これはメソッドです')
}
fun.fn() //これはメソッドです

先ほど作成したオブジェクトは、新しく追加されたプロトタイプ プロパティとプロトタイプ メソッドにアクセスできます。

3. 独自のプロパティとプロトタイプのプロパティ

まずコンストラクターを作成し、それに 2 つのプロトタイプ プロパティを追加しましょう。

//コンストラクタ関数 Fun() {}
//プロトタイプのプロパティとメソッドを追加します Fun.prototype.name = 'a bowl of porridge'
Fun.prototype.print = 関数(){
  console.log('これは関数です')
}

コンストラクタを介してオブジェクトを作成し、そのプロパティとメソッドを設定する

//コンストラクタを介してオブジェクトを作成する var fun = new Fun()
//オブジェクトにプロパティとメソッドを追加します fun.name = 'Yiwan Zhou'
fun.SayMe = 関数 () {
  console.log('これはSayMeです')
}

これで、 funオブジェクトには 2 つの独自のプロパティ/メソッドと 2 つのプロトタイプ プロパティ/メソッドができました。これらのプロパティとメソッドに順番にアクセスします。

//プロパティとメソッドにアクセスする console.log(fun.name) // Yiwan Zhou fun.SayMe() // これはSayMeです
fun.print() // これは関数です


nameプロパティにアクセスすると、JavaScript エンジンは fun オブジェクトのすべてのプロパティを走査し、name プロパティの値を返します。 SayMe() メソッドについても同様です。ただし、print() メソッドになると、 JavaScriptエンジンはオブジェクトのすべてのプロパティをトラバースします。この時点では、print() メソッドは見つかりません。次に、 JavaScriptエンジンは、現在のオブジェクトを作成したコンストラクター関数のプロトタイプ、つまりFun.prototypeにアクセスします。そのようなプロパティがある場合は、すぐに戻りますが、ない場合はundefinedを返すか、例外をスローします。

結論:独自のプロパティがある場合は、独自のプロパティへのアクセスを優先し、その後にプロトタイプ プロパティにアクセスします。

3.1 独自のプロパティまたはプロトタイププロパティの検出

所有プロパティとプロトタイプ プロパティの概念と使用法はわかりましたが、プロパティがフリー プロパティかオリジナル プロパティかはどのようにしてわかるのでしょうか。JavaScript では、プロパティの状態を検出する次の 2 つの方法が用意されています。

Object.prototype.hasOwnProperty(prop)メソッドを使用して、prop プロパティがフリー プロパティであるかどうかを検出します。このメソッドはブール値を返します。所有プロパティである場合は true を返し、そうでない場合は false を返します。

in キーワードを使用して、オブジェクトとプロトタイプ チェーンに指定されたプロパティがあるかどうかを検出します。

テストコードは次のとおりです。

// Object.prototype.hasOwnProperty(prop) メソッドを使用して、所有プロパティであるかどうかを確認します console.log(fun.hasOwnProperty('name')) // true
console.log(fun.hasOwnProperty('print')) // false
// 存在しない属性が検出された場合も、結果は false になります
console.log(fun.hasOwnProperty('SayMe')) // true

// in 演算子経由 console.log('name' in fun) // true
console.log('print' in fun) // true
console.log('SayMe' in fun) // true

テストの結果、これら 2 つの方法ではプロパティが独自のプロパティであるかプロトタイプ プロパティであるかを検出できないことがわかりましたが、これら 2 つの方法を組み合わせると、独自のプロパティであるかプロトタイプ プロパティであるかを検出できます。

サンプルコードは次のとおりです。

関数 DetectionAttributes(obj, attr) {
  if (attr in obj) {
    obj.hasOwnProperty(attr) の場合 {
      // 独自の属性の場合は1を返す
      戻り値 1
    } それ以外 {
      // プロトタイププロパティの場合は0を返す
      0を返す
    }
  } それ以外 {
    // そのような属性がない場合は -1 を返します
    -1を返す
  }
}


テストは次のとおりです。

console.log(DetectionAttributes(fun, 'name')) // 1
console.log(DetectionAttributes(fun, 'print')) // 0
console.log(DetectionAttributes(fun, 'SayMe')) // 1

4. isPrototypeOf() メソッド

isPrototypeOf()メソッドは、オブジェクトが別のオブジェクトのプロトタイプ チェーン内に存在するかどうかを検出するために使用されます。存在する場合は true を返し、存在しない場合は false を返します。

サンプルコードは次のとおりです。

// プロトタイプオブジェクトに割り当てるオブジェクトを定義する var obj = function () {
  this.name = '一碗の周'
}
var Hero = function () {} // コンストラクタを定義する // 定義されたオブジェクトをコンストラクタのプロトタイプに割り当てる Hero.prototype = obj

// Hero を通じてオブジェクトを作成する var hero1 = new Hero()
var hero2 = 新しいHero()
// 作成された 2 つのオブジェクトが obj のプロトタイプ チェーン内にあるかどうかを判断します console.log(obj.isPrototypeOf(hero1)) // true
console.log(obj.isPrototypeOf(hero2)) // 真

5. 組み込みオブジェクトの拡張

JavaScript の組み込みオブジェクトの中には、 prototypeプロパティを持つものもあります。組み込みオブジェクトのprototypeプロパティを使用して、組み込みオブジェクトのプロパティとメソッドを拡張できます。

プロトタイプを通じて組み込みオブジェクトのプロパティとメソッドを拡張することは非常に柔軟であり、JavaScript 言語の具体的な内容は、個別の要件に応じて策定できます。

組み込みオブジェクトを拡張するには、次の 2 つの方法があります。

新しいプロパティとメソッドを直接追加します。

新しいプロパティまたはメソッドを追加するには、Object オブジェクトのdefineProperty()メソッドを使用します。この方法は、作成されたプロパティとメソッドがより安全であるため、最初の方法よりも優れています。

サンプルコードは次のとおりです。

// オブジェクトのプロパティとメソッドを拡張する // 最初のメソッドを使用する Object.prototype.MyPrint = function () {
  console.log('これはMyPrint()です')
}
// 2番目のメソッドを使用する Object.defineProperty(Object.prototype, 'MyInput', {
  値: 関数 () {
    console.log('これはMyInput()です')
  },
})
// Object.prototype.MyPrint() を呼び出す // これは MyPrint() です
Object.prototype.MyInput() // これはMyInput()です

6. 結論

この記事では、JavaScript におけるプロトタイプの概念、プロトタイプ プロパティ、独自のプロパティとプロトタイプ プロパティを検出する方法、組み込みオブジェクトを拡張する方法について説明します。

JavaScript プロトタイプの詳細に関するこの記事はこれで終わりです。JavaScript プロトタイプに関するより詳しい内容については、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続きご覧ください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Javascript プロトタイプ
  • JavaScript の isPrototypeOf 関数
  • jsネイティブ構文プロトタイプ、__proto__、コンストラクタの徹底的な理解
  • JavaScriptはプロトタイププロパティを使用して継承操作を実装する例
  • JS 配列の次元削減の実装 Array.prototype.concat.apply([], arr)
  • 先頭と末尾のスペースを削除する js String.prototype.trim 文字の拡張
  • JavaScript __proto__ とプロトタイプ

<<:  動的な色切り替えの実装コードをサポートするために、CSS で SVG 画像を参照します。

>>:  Mysql データベースのマスタースレーブ同期構成

推薦する

MySQL 5.7.17 のインストールと設定方法のグラフィックチュートリアル (Win7 の場合)

Windows 7 で MySQL 5.7.17 をインストールする方法についてのグラフィック チ...

MySQLの整数および文字列インデックスの無効化または暗黙的な変換に関する簡単な説明

目次問題の概要問題の再現問題の拡大結論は問題の概要今日、仕事中に、DBA が突然、SQL に暗黙的な...

CSS 配置レイアウト (位置、配置レイアウト スキル)

1. ポジショニングとは何ですか? CSS の position 属性には、absolute/re...

フィールドを結合するSQL関数

最近、関連テーブル内のすべてのフィールドをクエリし、それらを 1 つのフィールドに再グループ化する必...

MySQL 8.0 で列を素早く追加する方法

序文: MySQL 8.0 では高速な列追加がサポートされ、数秒で大きなテーブルにフィールドを追加で...

進捗バーのネイティブ JavaScript 実装

進捗バーを実装するためのJavaScriptの具体的なコードは参考までに。具体的な内容は次のとおりで...

Nginx で Http、Https、WS、WSS を設定する方法

前面に書かれた今日のインターネット分野では、Nginx は最も広く使用されているプロキシ サーバーの...

Vueはビデオ再生を実装するためにビデオタグを使用します

この記事では、ビデオタグを使用してビデオ再生を実装するVueの具体的なコードを参考までに共有します。...

MySQLのバージョンアップ方法を超詳しく解説

目次1. はじめに2. データベースをバックアップする3. オリジナルのMysqlをアンインストール...

HTML の入力の readonly 属性と disabled 属性の違いについて簡単に説明します。

「読み取り専用」と「無効」はどちらも、ユーザーがフォーム フィールドの内容を変更できないようにしま...

レム適応の一般的なパッケージ3つについて

序文以前、rem適応についての記事を書きましたが、具体的なパッケージは紹介しませんでした。今日は、よ...

CentOS での Django プロジェクトのデプロイに関する詳細なチュートリアル

基本環境パゴダ設置サービスパゴダにインストールされた[Pythonプロジェクトマネージャー]パゴダに...

MySQL データ圧縮パフォーマンス比較の詳細

目次1. テスト環境1.1 ハードウェアとソフトウェア1.2 テーブル構造2. テストの目的2.1 ...

Web Storage APIの使用に関する簡単な説明

目次1. ブラウザのローカルストレージ技術1.1、セッションストレージ1.2、ローカルストレージ2....

nginx プロキシ サーバーで双方向証明書検証を構成する方法

証明書チェーンを生成するスクリプトを使用して、ルート証明書、中間証明書、および 3 つのクライアント...