2015-02-24 8 views
6

Ich las darüber, wie die Javascript Prototyp Eigenschaft funktioniert mit Vererbung zusammen und begann dann durch den Angularjs Code zu suchen und kam mit einigen Fragen auf.Warum etwas Something.prototype.constructor zuweisen?

Zunächst einmal habe ich gelesen, dass die Eigenschaft prototype auf ein Objekt, das eine „Konstruktor“ Eigenschaft hat, die auf die ursprüngliche Funktion zurückweist, die verwendet wird, um das Objekt zu erstellen. So zum Beispiel:

// This is the constructor 
function Shape() { 
    this.position = 1; 
} 

// The constructor points back to the original function we defined 
Shape.protoype.constructor == Shape; 

Der Prototyp enthält auch alle andere Methoden oder Eigenschaften, die auf sie von uns oder von der Javascript-Sprache selbst definiert wurden, und diese werden von allen Instanzen des Objekts geteilt. Wenn Sie ein Objekt namens Platzes wollen von Shape erben müssen Sie Platz Prototyp gleich auf eine neue Instanz der Form, da der interne [[Prototyp]] auf Eigenschaft Square.prototype zum öffentlichen Objektwert der Shape.prototype Eigenschaft festgelegt wird .

function Square() {} 
Square.prototype = new Shape(); 
var square = new Square(); 
square.position; // This will output 1 

Das macht alles Sinn für mich.

jedoch die Angularjs Code, ich habe eine Frage über, um all dies verbunden zu sein scheint, aber tut etwas, das ich nicht verstehe. Es scheint nicht mit Vererbung zu tun hat, so kann ich verstehen, warum es Unterschiede geben würde, aber ich bin nur neugierig, warum sie es so schrieben sie.

Innerhalb Angularjs gibt es ein HashMap-Objekt und ein Lexer Objekt, aber sie sind anders noch erscheinen definiert instanziiert und in die gleichen genauen Art und Weise verwendet werden. Der Lexer Konstruktor wird zuerst definiert, und legen sie den Prototyp zu einem Objekt Literal enthalten Methoden, die von allen Instanzen der Lexer geteilt werden sollte. Das macht alles Sinn. Was ich nicht verstehe, ist, warum sie die Eigenschaft "constructor" angeben und sie auf "Lexer" setzen, wenn sie nicht für HashMap darunter sind.

var Lexer = function(options) { 
    this.options = options; 
}; 

// Notice they specify Lexer as the constructor even though they don't for HashMap below 
Lexer.prototype = { 
    constructor: Lexer, 
    lex: function(text) { ... }, 
    is: function(ch, chars) { ... }, 
    peek: function(i) { ... }, 
    isNumber: function(ch) { ... }, 
    isWhitespace: function(ch) { ... }, 
    isIdent: function(ch) { ... }, 
    isExpOperator: function(ch) { ... }, 
    throwError: function(error, start, end) { ... }, 
    readNumber: function() { ... }, 
    readIdent: function() { ... }, 
    readString: function(quote) { ... } 
}; 

Dann, wenn Sie an der HashMap Code aussehen, tun sie das gleiche, außer dass sie den Konstruktor Eigenschaft nicht angeben. Warum ist das? Es scheint genau zu funktionieren und ich habe getestet, dass der Konstruktor immer noch aufgerufen wird.

// The HashMap Constructor 
function HashMap(array, isolatedUid) { 
    if (isolatedUid) { 
     var uid = 0; 
     this.nextUid = function() { 
      return ++uid; 
     }; 
    } 
    forEach(array, this.put, this); 
} 

HashMap.prototype = { 
    put: function(key, value) { ... }, 
    get: function(key) { ... }, 
    remove: function(key) { ... } 
}; 

So ist der Konstruktor Eigenschaft optional, wenn kein Erbe ist, so vielleicht eine Person den Lexer und eine andere die HashMap schrieb und entschied man sich, den Konstruktor angeben?

+0

siehe auch [Definieren eines Javascript-Prototyps] (http://stackoverflow.com/q/17474390/1048572) – Bergi

+0

@Bergi Danke, das hilft. – Triad

Antwort

8

Standardmäßig hat jeder Prototyp eine constructor Eigenschaft, die auf die Funktion verweist, die es „gehört“.

function A() { 
 
} 
 

 
console.log(A.prototype.constructor === A); // true

Wenn Sie einen Prototyp in seiner Gesamtheit mit einem Objektliteral oder mit einem anderen konstruierten Prototyp überschreiben, dieser constructor Wert weg erhalten abgewischt wird und nicht definiert oder mit einem anderen Wert gelassen werden.

function A() { 
 
} 
 
A.prototype = { 
 
    greeting: "Hello!" 
 
}; 
 

 
console.log(A.prototype.constructor === A); // false

Der Prototyp constructor Eigenschaft ist nicht für den Konstruktor benötigt, um richtig zu funktionieren, aber die Menschen werden oft prototype.constructor wieder auf seinen Anfangswert, um die Konsistenz zu erhalten neu zuzuweisen, und das ist, was Sie sehen für Lexer.

Bedenken Sie:

function A() { 
 
} 
 

 
function B() { 
 
} 
 

 
B.prototype = Object.create(A.prototype); 
 

 
var b = new B(); 
 

 
console.log(b.constructor === A); // true 
 
console.log(b.constructor === B); // false 
 

 
B.prototype.constructor = B; 
 

 
console.log(b.constructor === A); // false 
 
console.log(b.constructor === B); // true

Man braucht sich nur, warum dies ausgelassen wurde für HashMap spekulieren kann. Ich bezweifle, dass es aus irgendeinem guten Grund getan wurde und vielleicht nur ein Versehen gewesen ist.

+0

Danke für die Klärung. Ich fühle mich irgendwie dumm, das nicht zu sehen, aber ich habe es vorher anders angeschaut, weil ich verwirrt war, warum sie "Konstruktor: Lexer" anstatt "Konstrukteur: neuer Lexer()" verwendeten, aber ich sehe jetzt, warum das keinen Sinn ergibt überhaupt. Es ist der SubConstructor.prototype = new Constructor(), der das Schlüsselwort "new" haben sollte, das dann die Eigenschaft "SubConstructor.prototype.constructor" automatisch "Constructor" zuweist, was ein anderes Szenario ist als das Angular-Szenario oben. – Triad

+1

@Triad Ja, das ist richtig. Bedenken Sie, dass die Verwendung von 'SubConstructor.prototype = new Constructor()' zum Erstellen von Prototypen eine veraltete Methode ist. Heutzutage wäre es 'SubConstructor.prototype = Object.create (Konstruktor.prototype);' – JLRishe

+0

Ah, gut zu wissen, nochmals vielen Dank. – Triad

Verwandte Themen