ここでは、オブジェクトの内部プロトタイプ (__proto__) とコンストラクターのプロトタイプ (prototype) の関係について説明します。
1. すべてのコンストラクター/関数の __proto__ は、空の関数 (空の関数) である Function.prototype を指します
Number.__proto__ === Function.prototype // true
Boolean.__proto__ === Function.prototype // true
文字列。 __proto__ === Function.prototype // true
Object.__proto__ === Function.prototype // true
Function.__proto__ === Function.prototype // true
Array.__proto__ === 関数. プロトタイプ // 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__ === オブジェクト.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 のタイプが「function」である唯一のプロトタイプでもあります。他のコンストラクターのプロトタイプはオブジェクトです。以下のように
console.log(typeof Function.プロトタイプ) // 関数
console.log(typeof Object.prototype) // オブジェクト
console.log(typeof Number.prototype) // オブジェクト
console.log(typeof Boolean.prototype) // オブジェクト
console .log(typeof String.prototype) // オブジェクト
console.log(typeof Array.prototype) // オブジェクト
console.log(typeof RegExp.prototype) // オブジェクト
コンソール。 log(typeof Error .prototype) // オブジェクト
console.log(typeof Date.prototype) // オブジェクト
console.log(typeof Object.prototype) // オブジェクト
ああ、それは上でも述べられていますが、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 = 新しい日付
var err = new Error('例外')
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 の内部プロトタイプは常にそのインスタンス オブジェクトを指します。コンストラクターのプロトタイプ。
各オブジェクトにはコンストラクターを取得できるコンストラクター属性があるため、次の出力結果も同じです。
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 に代入されるのは、オブジェクト リテラル メソッドを使用して定義されたオブジェクトのコンストラクターが、ルート コンストラクターを指します。 Object.prototype は空のオブジェクト {} であり、{} は当然のことながら {getName: function(){}} とは異なります。次のように
var p = {}
console.log (Object.prototype) // 空のオブジェクトです {}
console.log(p.constructor === Object) // オブジェクト リテラル モードで定義されたオブジェクトのコンストラクターは Object
console.log(p .constructor.prototype === Object.prototype) // true の場合、説明はありません
上記のコードで使用されている __proto__ は現在 IE6 ではサポートされていません/ 7/8/9。 IE9 では、Object.getPrototypeOf(ES5) を使用してオブジェクトの内部プロトタイプを取得できます。
var p = {}
var __proto__ = Object .getPrototypeOf(p)
console.log(__proto__ === Object.prototype) // true