ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript における __proto__ とプロトタイプの関係の簡単な分析

JavaScript における __proto__ とプロトタイプの関係の簡単な分析

零到壹度
零到壹度オリジナル
2018-03-22 11:37:151123ブラウズ

今回は JavaScript における __proto__ とプロトタイプの関係について簡単に分析します。以下は実際のケースです。エディターに従ってご覧ください。

1. すべてのコンストラクター/関数の __proto__ は、空の関数である Function.prototype を指します (Empty function)

Number.__proto__ === Function.prototype  // true
Boolean.__proto__ === Function.prototype // true
String.__proto__ === Function.prototype  // true
Object.__proto__ === Function.prototype  // true
Function.__proto__ === Function.prototype // true 
Array.__proto__ === Function.prototype   // true
RegExp.__proto__ === Function.prototype  // true
Error.__proto__ === Function.prototype   // true
Date.__proto__ === Function.prototype    // true

JavaScript には合計 12 個の組み込み (ビルトイン) コンストラクター/オブジェクトがあります (JSON は ES5 で新たに追加されました)。アクセス可能なコンストラクターは以下の 8 つです。 Global などの残りの部分には直接アクセスできません。引数は関数が呼び出されたときに JS エンジンによってのみ作成されます。Math、JSON はオブジェクトの形式で存在し、新しいものは必要ありません。それらの __proto__ は Object.prototype です。以下の通り

Math.__proto__ === Object.prototype  // true 
JSON.__proto__ === Object.prototype  // true

上記の「すべてのコンストラクター/関数」には、確かにカスタムのものも含まれます。以下の通り

// 函数声明
function Person() {}
// 函数表达式
var Man = function() {}
console.log(Person.__proto__ === Function.prototype) // true
console.log(Man.__proto__ === Function.prototype)    // true

これはどういう意味ですか?

ルート コンストラクターの Object や Function 自体も含め、すべてのコンストラクターは Function.prototype から取得されます。すべてのコンストラクターは Function.prototype のプロパティとメソッドを継承します。長さ、呼び出し、適用、バインドなど (ES5)。

Function.prototype は、XXX.prototype の唯一のタイプでもあります。 「関数」のプロトタイプ。他のコンストラクターのプロトタイプはオブジェクトです。例:

console.log(typeof Function.prototype) // function
console.log(typeof Object.prototype)   // object
console.log(typeof Number.prototype)   // object
console.log(typeof Boolean.prototype)  // object
console.log(typeof String.prototype)   // object
console.log(typeof Array.prototype)    // object
console.log(typeof RegExp.prototype)   // object
console.log(typeof Error.prototype)    // object
console.log(typeof Date.prototype)     // object
console.log(typeof Object.prototype)   // object

ああ、これが空の関数であることも上で説明しましたが、alert(Function.prototype) を見てみましょう。

すべてのコンストラクター (組み込みおよびカスタムを含む) の __proto__ が Function.prototype であることがわかったので、Function.prototype の __proto__ は誰でしょうか?

JavaScript の関数も第一級市民であることを皆さんも聞いたことがあると思いますが、これをどのように示すことができますか?以下に示すように

console.log(Function.prototype.__proto__ === Object.prototype) // true

これは、すべてのコンストラクターも通常の JS オブジェクトであり、コンストラクターに属性を追加/削除できることを示しています。同時に、Object.prototype のすべてのメソッド (toString、valueOf、hasOwnProperty など) も継承します。

最後に、Object.prototype の __proto__ は誰ですか?

Object.prototype.__proto__ === null  // true

はトップに到達しましたが、nullです。

2. すべてのオブジェクトの __proto__ は、そのコンストラクターのプロトタイプを指します

上記では、すべての組み込みコンストラクターとカスタム コンストラクターの __proto__ をテストしました。これらすべてのインスタンス オブジェクトの __proto__ を見てみましょう。 _proto__ は誰を指すのでしょうか?

まず JavaScript エンジンの組み込みコンストラクターを見てください

var obj = {name: 'jack'}
var arr = [1,2,3]
var reg = /hello/g
var date = new Date
var err = new Error('exception')
console.log(obj.__proto__ === Object.prototype) // true
console.log(arr.__proto__ === Array.prototype)  // true
console.log(reg.__proto__ === RegExp.prototype) // true
console.log(date.__proto__ === Date.prototype)  // true
console.log(err.__proto__ === Error.prototype)  // true

次に、カスタム コンストラクターを見てください。ここで Person が定義されています

function Person(name) {
this.name = name
}
var p = new Person('jack')
console.log(p.__proto__ === Person.prototype) // true

p は Person のインスタンス オブジェクトであり、p の内部プロトタイプは常に を指します。コンストラクター Person のプロトタイプ。

各オブジェクトはコンストラクタ属性を持ち、そのコンストラクタを取得できるので、以下の印刷結果も同一です

function Person(name) {
this.name = name
}
var p = new Person('jack')
console.log(p.__proto__ === p.constructor.prototype) // true

上記の人はプロトタイプに属性やメソッドを追加していませんが、ここではプロトタイプにgetNameメソッドを追加しています

function Person(name) {
this.name = name
}
// 修改原型
Person.prototype.getName = function() {}
var p = new Person('jack')
console.log(p.__proto__ === Person.prototype) // true
console.log(p.__proto__ === p.constructor.prototype) // true

p.__proto__、Person.prototype、および p.constructor.prototype はすべて同一である、つまり、すべて同じオブジェクトを指していることがわかります。

プロトタイプを別の方法で設定した場合、結果は少し異なります

function Person(name) {
this.name = name
}
// 重写原型
Person.prototype = {
getName: function() {}
}
var p = new Person('jack')
console.log(p.__proto__ === Person.prototype) // true
console.log(p.__proto__ === p.constructor.prototype) // false

person.prototypeはここで直接書き換えられています(注: 前の例はプロトタイプを変更するものです)。出力は、p.__proto__ がまだ p.constructor.prototype ではなく Person.prototype を指していることを示しています。

これも分かりやすいですが、 person.prototype に代入されるのはオブジェクトリテラル {getName: です。 function(){}}、オブジェクト リテラル メソッドを使用して定義されたオブジェクトのコンストラクターは、ルート コンストラクター Object を指します。Object.prototype は空のオブジェクトです。{}、{} は当然のことながら {getName: と同じです。 function(){}} は等しくありません。以下の通り

var p = {}
console.log(Object.prototype) // 为一个空的对象{}
console.log(p.constructor === Object) // 对象直接量方式定义的对象其constructor为Object
console.log(p.constructor.prototype === Object.prototype) // 为true,不解释

上記のコードで使用されている __proto__ は、現在 IE6/7/8/9 ではサポートされていません。 IE9 では、Object.getPrototypeOf(ES5) を使用してオブジェクトの内部プロトタイプを取得できます。

りー

以上がJavaScript における __proto__ とプロトタイプの関係の簡単な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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