2010-08-30 10 views

Respuesta

38

Bueno, de manera que se puede volver a utilizar la lógica de la Person constructor se invoca con call o apply, por ejemplo:

function Person(gender) { 
    this.gender = gender; 
} 

function Student(gender) { 
    Person.apply(this, arguments); 
} 
Student.prototype = new Person(); // make Student inherit from a Person object 
Student.prototype.constructor = Student; // fix constructor property 

var foo = new Student('male'); 
foo.gender;    // "male" 
foo instanceof Student; // true 
foo instanceof Person; // true 

Si desea evitar la ejecución de la Person constructor cuando se llama sin argumentos (como en la línea de: Student.prototype = new Person();), puede detectarlo, por ejemplo:

function Person(gender) { 
    if (arguments.length == 0) return; // don't do anything 
    this.gender = gender; 
} 
+1

@CMS Para la segunda porción 'if (arguments.length == 0) return;', ¿hay alguna manera de manejar constructores donde los argumentos NO son necesarios? En esa situación, ¿estoy obligado a llamar al constructor? –

+0

He intentado muchos métodos diferentes ('Object.create',' Person.prototype', temp functions ...) pero todos fallan o tienen errores (propiedades indefinidas, oscuras, etc.). Gracias por esta respuesta, ¡finalmente una que realmente funciona! – TheBronx

0
// define the Person Class 
function Person(name) { 
    this.personname = name; 
} 

Person.prototype.walk = function(){}; 
Person.prototype.sayHello = function(){ 
    alert (this.personname); 
}; 

https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/constructor


El código completo:

<script> 
// define the Person Class 
function Person(name) { 
    this.personname = name; 
} 

Person.prototype.walk = function(){}; 
Person.prototype.sayHello = function(){ 
    alert (this.personname); 
}; 

// define the Student class 
function Student() {} 

// inherit Person 
Student.prototype = new Person("test"); 

// correct the constructor pointer because it points to Person 
Student.prototype.constructor = Student; 

// replace the sayHello method 
Student.prototype.sayHello = function(){ 
    alert('hi, I am a student and my name is \'' + this.personname + '\''); 
} 

// add sayGoodBye method 
Student.prototype.sayGoodBye = function(){ 
    alert('goodBye'); 
} 

var student1 = new Student(); 
student1.sayHello(); 
student1.sayGoodBye(); 
</script> 
+1

Creo que esto funciona bien si siempre desea "prueba" como el nombre de la persona, pero esto no es lo que quiero decir cuando le pregunto a llamarlo desde el Constructor del estudiante – kgarske

9

respuesta aceptada parece ser incorrecta . Sobre la base de lo que Mozilla says about OO JavaScript, forma correcta de hacerlo es:

var Person = function(firstName) { 
    this.firstName = firstName; 
}; 

function Student(firstName, subject) { 
    // Call the parent constructor, making sure (using Function#call) 
    // that "this" is set correctly during the call 
    Person.call(this, firstName); 

    // Initialize our Student-specific properties 
    this.subject = subject; 
}; 

// Create a Student.prototype object that inherits from Person.prototype. 
// Note: A common error here is to use "new Person()" to create the 
// Student.prototype. That's incorrect for several reasons, not least 
// that we don't have anything to give Person for the "firstName" 
// argument. The correct place to call Person is above, where we call 
// it from Student. 
Student.prototype = Object.create(Person.prototype); // See note below 

// Set the "constructor" property to refer to Student 
Student.prototype.constructor = Student; 

// Example usage: 
var student1 = new Student("Janet", "Applied Physics"); 

Como se puede ver claramente, Mozilla especifica que se trata de un error común el uso de "nueva persona()" para crear el Student.prototype. Por lo tanto, la respuesta aceptada es engañosa.

He probado esto en mi proyecto en curso y la forma de Mozilla es correcta, mientras que la respuesta anterior no funciona.

0

Por todos los demás comentarios, creé un ejemplo que funciona para mí. Como no utilicé el prototipo explícitamente, espero no perder un punto importante.

// variable for tracking instantiations and checking the uniqueness of the objects 
var instances = 0; 

var Generic = function() { 
    this.instanceId = ++instances; 
    this.toString = function() {return 'Generic [iid='+ this.instanceId +']'}; 
    console.log('constructor-invoke: Generic ('+ this.instanceId +')'); 
}; 

var SpecificName = function(inName) { 
    Generic.call(this); 
    this.getName = function() { return inName; };  
    var superToString = this.toString.bind(this); // binds the inner function 'this' to this SpecificName instance 
    this.toString = function() { 
     return 'SpecificName [iid='+ this.instanceId +', name='+ this.getName() +', super.toString='+ superToString() +']' 
    } 
    console.log('constructor-invoke: SpecificName ('+ this.instanceId +')'); 
}; 

var SpecificNames = function(inFirstName, inLastName) { 
    SpecificName.call(this, inLastName +', '+ inFirstName); 
    var superToString = this.toString.bind(this); 
    this.toString = function() { 
     return 'SpecificNames [iid='+ this.instanceId +', name='+ this.getName() +', super.toString='+ superToString() +']' 
    } 
    console.log('constructor-invoke: SpecificNames ('+ this.instanceId +')'); 
}; 

var g = new Generic(); 
var sn = new SpecificName('Run Forest Run'); 
var sns = new SpecificNames('Forest','Gump'); 

console.log('g: '+ g.toString()); 
console.log('sn: '+ sn.toString()); 
console.log('sns: '+ sns.toString()); 

conduce a este resultado:

constructor-invoke: Generic (1) 
constructor-invoke: Generic (2) 
constructor-invoke: SpecificName (2) 
constructor-invoke: Generic (3) 
constructor-invoke: SpecificName (3) 
constructor-invoke: SpecificNames (3) 
g: Generic [iid=1] 
sn: SpecificName [iid=2, name=Run Forest Run, super.toString=Generic [iid=2]] 
sns: SpecificNames [iid=3, name=Gump, Forest, super.toString=SpecificName [iid=3, name=Gump, Forest, super.toString=Generic [iid=3]]] 
Cuestiones relacionadas