2011-07-07 22 views
24

Digamos que tengo el siguiente fragmento de código.cómo llamar al constructor padre?

function test(id) { alert(id); } 

testChild.prototype = new test(); 

function testChild(){} 

var instance = new testChild('hi'); 

¿Es posible obtener alert('hi')? Obtengo undefined ahora.

Respuesta

6

Así es como se hace esto en CoffeeScript:

class Test 
    constructor: (id) -> alert(id) 

class TestChild extends Test 

instance = new TestChild('hi') 

No, No estoy empezando una guerra santa. En cambio, estoy sugiriendo que echar un vistazo al código JavaScript resultante para ver cómo se podría implementar subclases:

// Function that does subclassing 
var __extends = function(child, parent) { 
    for (var key in parent) { 
    if (Object.prototype.hasOwnProperty.call(parent, key)) { 
     child[key] = parent[key]; 
    } 
    } 
    function ctor() { this.constructor = child; } 
    ctor.prototype = parent.prototype; 
    child.prototype = new ctor; 
    child.__super__ = parent.prototype; 
    return child; 
}; 

// Our code 
var Test, TestChild, instance; 

Test = function(id) { alert(id); }; 

TestChild = function() { 
    TestChild.__super__.constructor.apply(this, arguments); 
}; __extends(TestChild, Test); 

instance = new TestChild('hi'); 

// And we get an alert 

verlo en acción en http://jsfiddle.net/NGLMW/3/.

Para mantenerse correcto, el código se modifica ligeramente y se comenta para que sea más legible, en comparación con la salida de CoffeeScript.

+0

+1 para un buen análisis y ejemplo de jsFiddle – JCotton

0

Debe declarar el function testChild() antes de configurar su prototipo. Luego debe llamar al testChild.test para llamar al método. Creo que quiere establecer testChild.prototype.test = test, luego puede llamar al testChild.test('hi') y debería resolverse correctamente.

+0

// todavía no funciona .. – Moon

+0

// sí ... Me puede llamar manualmente prueba, pero lo que yo quiero hacer es prueba de llamada() sin invocar ella como podamos en otros lenguajes OOP. – Moon

3

Al aprovechar variable arguments y el método apply(), puede hacerlo de esta manera. Aquí hay un fiddle para este ejemplo.

function test(id) { alert(id); } 
function testChild() { 
    testChild.prototype.apply(this, arguments); 
    alert('also doing my own stuff'); 
} 
testChild.prototype = test; 
var instance = new testChild('hi', 'unused', 'optional', 'args'); 
+0

Probablemente sea la solución con más navegadores que aprovecha estándares de lenguaje bien definidos. –

+0

También tenga en cuenta que esto probablemente se puede reescribir como 'this .__ proto __. Apply (this, arguments)' por lo que es más genérico y reutilizable. Y también tenga en cuenta que esto no funcionará si define su herencia usando 'Object.create' como en' testChild.prototype = Object.create (test.prototype); 'que parece ser una forma bastante aceptada de crear herencia en la naturaleza . –

98

JS programación orientada a objetos ...

// parent class 
var Test = function(id) { 
    console.log(id); 
}; 

// child class 
var TestChild = function(id) { 
    Test.call(this, id); // call parent constructor 
}; 

// extend from parent class prototype 
TestChild.prototype = Object.create(Test.prototype); // keeps the proto clean 
TestChild.prototype.constructor = TestChild; // repair the inherited constructor 

// end-use 
var instance = new TestChild('foo'); 
+1

Gracias, definitivamente la manera de hacer esto en JS: P –

+0

Se ensucia cadenas de prototipos haciéndolo de esta manera. La forma de hacerlo es, en realidad, más parecida a http://js-bits.blogspot.com.au/2010/08/javascript-inheritance-done-right.html – papercowboy

+0

@cayuu. ¿Cómo se estropea esta cadena de prototipos? – roylaurie

14

usted ya tiene muchas respuestas, pero voy a tirar de la manera ES6, que en mi humilde opinión es la nueva forma estándar de hacer esto.

class Parent { 
    constructor() { alert('hi'); } 
} 
class Child extends Parent { 
    // Optionally include a constructor definition here. Leaving it 
    // out means the parent constructor is automatically invoked. 
    constructor() { 
    // imagine doing some custom stuff for this derived class 
    super(); // explicitly call parent constructor. 
    } 
} 

// Instantiate one: 
var foo = new Child(); // alert: hi 
+0

Buen punto. Desafortunadamente, 'super()' no es compatible incluso con IE11 (http://kangax.github.io/compat-table/es6/), que podría ser un problema en entornos productivos. – BurninLeo

+0

Buen recordatorio Como de costumbre, cuando es posible, es una buena idea transpilar su fuente a ES5 por esta y otras incompatibilidades. Puede hacerlo utilizando herramientas como Webpack, Typescript, etc. – Sk606

Cuestiones relacionadas