2014-12-16 25 views
9

Ho notato che lo Function.prototype ha un metodo toMethod() in JavaScript sperimentale, ma cosa fa effettivamente? E come lo uso?Cosa fa Function.prototype.toMethod()?

+1

Forse correlato: https://esdiscuss.org/topic/any-tomethod-use-case#content-1 –

+0

Non ho mai fatto alcun mix o composizione di classe quando si tratta di ereditarietà. quindi non capisco ancora di cosa stiano parlando o come usarlo –

+1

@Edwin - Non penso che sia pensato per essere utilizzato dallo sviluppatore JavaScript casuale. È una funzione di livello molto profondo da utilizzare nelle librerie JavaScript avanzate che dipendono da alcune caratteristiche dell'ereditarietà dei prototipi che sono anche in stato "sperimentale" (come la funzione "' super() '") – JDB

risposta

10

Aggiornamento: il metodo toMethod era solo sperimentale e non lo ha fatto nello standard. L'oggetto casa è essenzialmente statica ora, l'unico modo per manipolare super è quello di cambiare la [[prototype]]:

var base = {…}; // as below 
var obj = Object.setPrototypeOf({ 
    foo() { // needs to use method definition syntax 
     super.foo(); 
    } 
}, base); 
obj.foo(); 

E 'molto simile al metodo di oggetti funzione bind. Tuttavia, invece di creare una nuova funzione con un valore associato this, crea una nuova funzione con un balzo [[HomeObject]], che è il riferimento che viene utilizzato per super chiamate:

[[HomeObject]] (Object): If the function uses super , this is the object whose [[GetPrototypeOf]] provides the object where super property lookups begin.

consideri questo esempio (non utilizzando qualsiasi classe sintassi):

var base = { 
    foo: function() { 
     console.log("base foo called on", this); 
    } 
}; 
base.foo(); // base foo called on base 
var obj = Object.create(base); 
obj.foo(); // base foo called on obj 

obj.foo = function() { 
    super.foo(); 
}; 
obj.foo(); // ReferenceError: this method has no home 
obj.bar = obj.foo.toMethod(obj); 
obj.bar(); // base foo called on obj 

obj.baz = function() { 
    super(); 
}; 
obj.baz(); // ReferenceError: this constructor has no parent class 
Reflect.setPrototypeOf(obj.baz, base.foo); 
obj.baz(); // base foo called on obj 
+0

Capisco come usare bind e che restituisca una nuova funzione con un contesto differente ma il ** [[HomeObject]] ** che non capisco –

+0

ho ora ho aggiunto un esempio su come potrebbe essere usato 'super' – Bergi

+0

Non ho dimestichezza con come funziona tutto questo, ma sembra che dovrebbe essere' obj.bar = obj.foo.toMethod (base); ', giusto? Non stai impostando '[[HomeObject]] su' base'? – JDB

-1

mia comprensione è che .toMethod è come la clonazione di una funzione. Si consideri l'esempio nella fonte che ho postato,

class P { } 
class C extends P { 
    foo() { 
     console.log("f"); 
     super(); 
    } 
} 
P.prototype.foo=C.prototype.foo; 
(new C).foo(); 

Qui si fa riferimento a un metodo di sottoclasse .foo nella superclasse, in modo che quando si chiama .foo, si farà riferimento P 's .foo che è C' s .foo e basta creato un ciclo.

Sembra che per risolvere questo problema, è possibile utilizzare .toMethod che "cloni" la funzione e dargli un diverso super/"casa" che si specifed:

P.prototype.foo = C.prototype.foo.toMethod(P.prototype); 

ora chiamando (new C).foo() non sarebbe andare avanti per sempre.

+0

ok c'è solo una cosa che non capisco e poi la prenderò. È ** super() ** che rappresenta la ** classe P ** –

+0

Penso che ora il metodo sia di proprietà di P quindi 'super' non sarebbe affatto disponibile. . –

+0

prima di chiamare ** ** toMethod questo è lo stesso in ES5: 'funzione P() {}' ' funzione C() {}' ' C.prototype = new P();' 'C.prototype.foo = function() { console.log ('f'); P(); } ' ' P.prototype.foo = C.prototype.foo; ' ' (nuovo C) .foo() ' –