2012-04-26 6 views
12
function F() { 
    return function() { 
     return {}; 
    } 
} 

var f = new F(); 
f instanceof F; // returns false 

Por lo que entiendo, si quiero que instanceof funcione, tengo que devolver this del constructor. Pero quiero que el constructor devuelva una función y no puedo asignarlo al this.¿Puede el constructor de JavaScript devolver la función y mantener la herencia?

Entonces, ¿esto es realmente imposible o se puede hacer de alguna manera, para f = new F() devolver una función y todavía f instanceof F para devolver cierto?

+7

Puede devolver una función, ya que una función es un objeto. Pero obviamente, 'f instanceof F' no sería cierto, ya que no es cierto. –

+1

Félix: ¿De la misma manera que las tautologías son tautológicas? :) –

+0

¿Por qué quieres que instanceof funcione? Generalmente se considera dañino. – zetlen

Respuesta

8
function F() { 
    var r = function() { 
     return {}; 
    }; 

    r.__proto__ = this.__proto__; 
    return r; 
} 

var f = new F(); 
f instanceof F; 
true 
f(); 
Object 

sólo funciona en los navegadores con __proto__

+0

Muchas gracias. Esto lo hara. – Sixtease

0

En ti, tu ejemplo F no es un constructor, es una función que devuelve un constructor anónimo al que llamas como nuevo. instanceof funciona al observar la cadena de prototipos, por lo que su código no funciona porque no ha configurado los prototipos correctamente.

Este page tiene una buena explicación de los constructores de JavaScript y la clase de subclase.

Eche un vistazo al siguiente código y vea si ayuda.

function F() { 
    this.whoami = 'F'; 
    this.whatami = 'F'; 

} 

function Sub() { 
this.whoami = 'G'; 
} 

Sub.prototype = new F(); 

function G() { 
    return new Sub; 
} 

var f = new G(); 
console.log(f instanceof F); // returns false 
console.log(f.whoami); 
console.log(f.whatami); 
​ 
5

Se podría, por supuesto, realizar todas las funciones parecen ser instanceof F estableciendo F.prototype = Function.prototype;.

Desafortunadamente, parece que ECMAScript no permite crear una subclase de funciones.

Sin embargo, puede hacerlo en Gecko utilizando el obsoleto __proto__ propiedad:

function F() { 
    function f() { 
     return {}; 
    } 
    f.__proto__ = F.prototype; 
    return f; 
} 
F.prototype.__proto__ = F.__proto__; 
+0

Esailia fue más rápido, por lo tanto, su respuesta fue aceptada. ¡Gracias de cualquier manera! – Sixtease

+0

@Sixtease Bastante, pero tenga en cuenta que su respuesta tal como está escrita no le permitirá, p. '.aplicar' o' .call' en su objeto, porque no tiene la línea adicional que yo hago. – Neil

+0

@Neil, qué es exactamente F.prototype .__ proto__ = F .__ proto__; ¿está haciendo? ¿Qué pasaría si no lo hago? – esp

1

Para cualquiera que venga a través de este hoy, con ES6/2015 hay una nueva sintaxis que se puede utilizar para evitar la __proto__ propiedad en desuso; Object.setPrototypeOf. Tenga en cuenta que MDN warns que esta es una operación lenta/costosa.

function F() { 
    const f = function() { 
     return {}; 
    } 
    Object.setPrototypeOf(f, F.prototype); 
    return f; 
} 

var f = new F(); 
f instanceof F; // returns true 
f(); // returns {} 

Tenga en cuenta también que se pone un poco raro si desea inicializar valores en el constructor. Debes configurarlos como accesorios en la función que devolverás, pero las adiciones posteriores al prototipo los referirán como 'esto'. p.ej.

function F() { 
    const f = function() { 
     return {}; 
    } 
    f.favoriteBand = 'The Books'; 
    Object.setPrototypeOf(f, F.prototype); 
    return f; 
} 
F.prototype.getFavoriteBand = function(){ return this.favoriteBand; } 

var f = new F(); 
f.getFavoriteBand() // returns 'The Books' 
Cuestiones relacionadas