Inhalt:
Mehrere Modi zum Erstellen von Objekten und des Erstellungsprozesses
Verständnis des Prototypkettenprototyps und prototype
und Mehrere Implementierungen der Beziehung __proto__
([[Prototype]]
)
Vererbung
a. Konstruktorerstellung
function Test() {// }
Prozess
Beim Erstellen einer Funktion wird standardmäßig ein Prototypattribut für Test erstellt, Test.prototype
Enthält einen Zeiger, der auf Object.prototype
Prototyp zeigt, der standardmäßig einen Konstruktor hat, und andere Methoden in Test.prototype.constructor = Test
Prototyp Geerbt von Objekt
// 调用构造函数创建实例 var instance = new Test()
Die Instanz hier enthält einen Zeiger auf das Konstrukt Der Prototyp der Funktion, (Der Zeiger heißt hier __proto__
in Chrome, was auch gleich [[Prototype]]
ist)
b. Prototypmodus
Aus dem oben Gesagten können wir erkennen, dass die standardmäßig erstellten Prototypeigenschaften nur über Konstruktoren und Eigenschaften verfügen, die von Object geerbt wurden. Der Prototypmodus besteht darin, Eigenschaften und Methoden zum Prototyp hinzuzufügen
Test.prototype.getName = ()=> { alert('name') }
Zu diesem Zeitpunkt. Die Instanzinstanz ist Wir haben die getName-Methode, da der Instanzzeiger auf Test.prototype
instance.__proto__ === Test.prototype
zeigt, wie in der folgenden Abbildung gezeigt
Hier können wir erkennen, dass die Instanzinstanz und der Konstruktor durch den Prototyp prototype
miteinander verbunden sind.
c. Kombinationsmodus
Wir verwenden diesen Modus am häufigsten. Es ist eigentlich eine andere Art, den Prototypmodus zu schreiben, mit nur einem kleinen Unterschied
function Test() {} Test.prototype = { getName() { alert('name') } }
Wir verwenden ihn oft direkt Beim Umschreiben der Prototyp-Methode wissen wir aus dem oben Gesagten, dass der Prototyp standardmäßig über ein eigenes Konstruktorattribut verfügt, das auf den Konstruktor selbst verweist. Was passiert also nach dem Umschreiben?
Test.prototype.constructor === Object // 而并不等于Test了// 因为重写以后相当于利用字面量方式创建一个实例对象,这个实例的构造函数是指向Object本身的
Natürlich können wir den Konstruktor auch manuell zuweisen
Test.prototype = { constructor: Test, getName() { alert('name') } }
Dann wird es wieder Fragen gebenconstructor
Was bringt das? Ich denke, die Bedeutung von Konstruktor besteht lediglich darin, den Konstruktor zu identifizieren, zu dem der Prototyp gehört.
Wenn ein bestimmtes Attribut abgerufen werden muss, wird es zuerst von der Instanz aus durchsucht. Wenn nicht, wird es entsprechend dem Prototyp durchsucht, auf den der Zeiger zeigt, und dann nach oben, bis der Zeiger der Instanz < ist 🎜> zeigt auf null und die Suche wird beendet. Beispiel: __proto__
// 1 读取nameinstance.name // 2 instance.__proto__ === Test.prototypeTest.prototype.name // 3 Test.prototype.__proto__ === Object.prototypeObject.prototype.name // 4Object.prototype.__proto__ === null
verwenden. delete
ein Konstruktor ist und ihre Prototypzeiger auf Array, Date, Function, String
verweisen. Sie sind genau wie die Object.prototype
, die ich hier definiert habe, aber sie sind nativ Test
Den Prototyp abrufen, auf den der Zeiger einer Instanz zeigt Object.getPrototypeOf()
Object.getPrototypeOf(instance) === Test.prototype
Bestimmen Sie, ob ein Attribut in der Instanz oder im Prototyp vorhanden ist, wie in der Abbildung gezeigt: hasOwnProperty
Operator, unabhängig davon, ob das Attribut aufzählbar ist oder nicht in
'name' in instance // true 'getName' in instance // true
// 一种就是使用hasOwnProperty判断在实例中 // 另一种判断在原型中 instance.hasOwnProperty('getName') === false && 'getName' in instance === true
Operation Das Symbol ist das gleiche, aber es werden nur aufzählbare Eigenschaften aufgelistet. Der Fehler in der ie8-Version besteht darin, dass for ... in
name是在实例中定义的,getName是在原型中定义的
Object.keys()
则不一样,它返回一个对象上所有可枚举的属性,仅仅是该实例中的
Object.keys(instance)// ["name"]
e.总结
以上讨论了构造函数,原型和实例的关系:
每个构造函数都有原型对象
每个原型对象都有一个constructor
指针指向构造函数
每个实例都有一个__proto__
指针指向原型
其实是一个道理,这里我们不难想到,将Child.prototype指向parent实例,就是利用原型实现的继承,而为了每个实例都拥有各自的colors和name,也就是基础属性,在Child的构造函数中call调用了Parent的构造函数,相当于每次实例化的时候都初始化一遍colors和name,而不是所有实例共享原型链中的colors和name。
继承的实质是利用构造函数的原型 = 某个构造函数的实例,以此来形成原型链。例如
// 定义父类function Parent() {}Parent.prototype.getName = ()=> { console.log('parent') }// 实例化父类let parent = new Parent()// 定义子类function Child() {} Child.prototype = parent // 实例化子类let child = new Child() child.getName() // parent// 此时 child.constructor === parent.constructor === Parent
a.最经典的继承模式
function Parent(name) {this.name = namethis.colors = ['red'] } Parent.prototype.getName = function() {console.log(this.name) }// 实例化父类let parent = new Parent()function Child(age, name) { Parent.call(this, name)this.age = age } Child.prototype = parent // 实例化子类let child = new Child(1, 'aaa') child.getName() // parent
这里会让我想到ES6中的class继承
class Parent { constructor(name) {this.name = namethis.colors = ['red'] } getName() { console.log(this.name) } }class Child extends Parent { constructor(age, name) {super(name) } } let child = new Child(1, 'aaa') child.getName() // parent
Das obige ist der detaillierte Inhalt vonVerstehen gängiger Muster und Prototypenketten. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!