C'è un modo che sembra un'eredità prototipica, ma è diverso in un solo modo.
In primo luogo permette di dare un'occhiata a uno dei standard ways di attuare eredità prototipo in javascript:
var MyClass = function(bar){
this.foo = bar;
};
MyClass.prototype.awesomeMethod = function(){
alert("I'm awesome")
};
// extends MyClass
var MySubClass = function(bar){
MyClass.call(this, bar); // <- call super constructor
}
// which happens here
MySubClass.prototype = Object.create(MyClass.prototype); // prototype object with MyClass as its prototype
// allows us to still walk up the prototype chain as expected
Object.defineProperty(MySubClass.prototype, "constructor", {
enumerable: false, // this is merely a preference, but worth considering, it won't affect the inheritance aspect
value: MySubClass
});
// place extended/overridden methods here
MySubClass.prototype.superAwesomeMethod = function(){
alert("I'm super awesome!");
};
var testInstance = new MySubClass("hello");
alert(testInstance instanceof MyClass); // true
alert(testInstance instanceof MySubClass); // true
Il prossimo esempio avvolge solo la struttura di cui sopra per tenere tutto pulito. E c'è un piccolo ritocco che sembra a prima vista compiere un miracolo. Tuttavia, tutto ciò che sta realmente accadendo è che ogni istanza della sottoclasse sta usando non il prototipo di Array come modello per la costruzione, ma piuttosto un'istanza di una matrice - così il prototipo della sottoclasse viene agganciato alla fine di un oggetto completamente caricato che passa l'anatra di un array - che poi copia. Se vedi ancora qualcosa di strano qui e ti infastidisce, non sono sicuro di poterlo spiegare meglio - quindi forse come funziona è un buon argomento per un'altra domanda. :)
var extend = function(child, parent, optionalArgs){ //...
if(parent.toString() === "function "+parent.name+"() { [native code] }"){
optionalArgs = [parent].concat(Array.prototype.slice.call(arguments, 2));
child.prototype = Object.create(new parent.bind.apply(null, optionalArgs));
}else{
child.prototype = Object.create(parent.prototype);
}
Object.defineProperties(child.prototype, {
constructor: {enumerable: false, value: child},
_super_: {enumerable: false, value: parent} // merely for convenience (for future use), its not used here because our prototype is already constructed!
});
};
var Vector = (function(){
// we can extend Vector prototype here because functions are hoisted
// so it keeps the extend declaration close to the class declaration
// where we would expect to see it
extend(Vector, Array);
function Vector(){
// from here on out we are an instance of Array as well as an instance of Vector
// not needed here
// this._super_.call(this, arguments); // applies parent constructor (in this case Array, but we already did it during prototyping, so use this when extending your own classes)
// construct a Vector as needed from arguments
this.push.apply(this, arguments);
}
// just in case the prototype description warrants a closure
(function(){
var _Vector = this;
_Vector.sum = function sum(){
var i=0, s=0.0, l=this.length;
while(i<l){
s = s + this[i++];
}
return s;
};
}).call(Vector.prototype);
return Vector;
})();
var a = new Vector(1,2,3); // 1,2,3
var b = new Vector(4,5,6,7); // 4,5,6,7
alert(a instanceof Array && a instanceof Vector); // true
alert(a === b); // false
alert(a.length); // 3
alert(b.length); // 4
alert(a.sum()); // 6
alert(b.sum()); // 22
Presto avremo classe e la possibilità di estendere le classi native in ES6, ma che può essere un altro anno ancora. Nel frattempo spero che questo aiuti qualcuno.
quanti di questi * * Vector array avete in programma di un'istanza? 2? Centinaia? –
Hai dimenticato una var. 'var vector = [];'. – Thai
Più di migliaia. – shino