2013-06-22 26 views
5

So come utilizzare i metodi per modificare il contesto di una chiamata funzione/metodo: applica, associa, chiama. La mia domanda è questa, c'è un modo per verificare se una funzione/metodo ha già avuto il suo contesto impostato?Controllo contesto metodo/metodo JavaScript

// given 
var beta; 

function alpha() { 
    return this; 
} 

function isContextSet (fn) { 
    /* check for context binding on fn */ 
} 

beta = alpha.bind("hello"); 

isContextSet(alpha); // returns false 
isContextSet(beta); // returns true 

Penso di conoscere la risposta a questa già, ma ho pensato di chiedere in ogni caso, se non altro per ragioni diverse: 1. confermare la mia ipotesi, o 2. imparare qualcosa. Sono sicuro di non essere il primo a porre questa domanda, ma non ho avuto alcuna idea su come trovare effettivamente una risposta poiché tutto ciò che ottengo sono le risposte a come usare: .apply(), .call(), o. bind().

+1

Forse questo aiuta: [A quale oggetto è associata la funzione javascript (qual è il suo "questo")?] (Http://stackoverflow.com/q/14307264/218196). –

+2

_ "ha già avuto il suo contesto impostato" _ Cosa intendi con "già"? '.apply()', '.call()' e '.bind()' non impostano permanentemente 'this' per ogni volta che la funzione viene chiamata (notando che' .bind() 'restituisce una funzione _new_ che in modo permanente ha uno specifico 'this', ma in realtà non cambia la funzione _original_). Ogni modo possibile per chiamare una funzione imposta 'this' a _qualcosa_ - è solo in alcuni modi farlo implicitamente, alcuni lo fanno esplicitamente ... – nnnnnn

+0

Ho aggiunto del codice per mostrare quello che cerco di ottenere. Capisco come funzionano i tre metodi, e so come controllare il contesto di una funzione/metodo all'interno del corpo dell'invocazione. Come controlli il contesto dall'esterno dell'invocazione, come ho mostrato sopra? Non riesco a pensare a un modo per farlo affatto in JS. – kalisjoshua

risposta

2

No.

In realtà, non è corretto riferirsi al binding come "cambiare" il contesto. Quello che fa è trasformare una funzione in un'altra che chiama il primo con un particolare contesto.

Le funzioni possono essere vincolate in molti modi. Per esempio, ho potuto legare da solo:

function bind(fn,ctxt){ 
    return function(){ 
     fn.apply(ctxt,arguments); 
    }; 
} 

Oppure, potrei legarlo con Function.prototype.bind, o di uno spessore che fa la stessa cosa, o _.bind di sottolineatura. Potrei legarlo agli argomenti iniziali oltre al contesto. In ogni caso, non c'è modo di dire cosa è successo senza essenzialmente eseguire la funzione.

Il binding è solo uno dei molti modi per trasformare una funzione in un'altra. Potrei anche trasformare una funzione per eseguire un secondo da ora, o essere eseguita due volte. Non c'è nulla di magico nel legare; crea solo una nuova funzione basata su quella vecchia. Non esiste una variabile speciale chiamata [[bound_to]] impostata sulla funzione che potresti essere in grado di esaminare (a meno che tu non usi la tua implementazione personalizzata di bind, come suggerisce un'altra risposta). Non esiste un modo post facto per determinare come è stata trasformata la funzione.

Il più vicino che posso immaginare è controllare la funzione associata a una versione non associata e vedere se sono uguali.

function log_this(){console.log(this);} 
var bound_func=log_this.bind(my_var); 
console.log(log_this===bound_func); // FALSE 
+1

Penso che riassumi questo abbastanza bene. Sono d'accordo che non c'è modo di testare veramente il contesto, come sto definendo sopra. JavaScript fornisce semplicemente troppi modi per aggirare la situazione che sto cercando di testare. – kalisjoshua

0

cosa si potrebbe fare è qualcosa di simile:

function f(context, whatever) { 
    if(this !== context) { 
     //context has been changed 
    } 
} 

var y = f.bind(thingy); 
y(otherThingy, something); 

Si potrebbe anche avere una funzione bind personalizzato e hanno una sorta di un hack come questo:

function bind(func, context) {  
    var newFunc = func.bind(context); 
    newFunc._this = context; 
    return newFunc; 
} 

function checkContext(func, context) { 
    return func._this !== context; 
} 
+0

Ed ecco un violino che dimostra la mia versione di una funzione di bind personalizzata, che stavo per pubblicare come risposta quando ho visto che l'avevate già coperto con un'idea simile: http: // jsfiddle .net/jx4fY/ – nnnnnn

-1

credo che questo sia domanda interessante per chi come l'amore JavaScirpt e spero che questa è la risposta che cosa state cercando:


var isContextSet = function (fn) { 
    var testThis = {}; //unique object for testing what is this inside fn 
    return fn.call(testThis) !== testThis; 
} 

cerco di "set" questo all'interno fn : fn.call(testThis); e se tale funzione ha restituito il riferimento all'oggetto appena creato (testThis), quindi non è vincolato. Spero che si ottiene :)

EDIT: Questo funziona quando fn Retuns questo (come mostrato in questione). Altrimenti non è possibile definire isContextSet correttamente.

+0

Cosa succede se la funzione non restituisce questo valore, ma un altro valore o nessun valore? Questo genererà molti falsi positivi. Esempio più semplice: 'isContextSet (function() {})' produrrà 'true', anche se la funzione non è associata a un valore specifico. –

+0

Nella funzione di esempio di domande restituisce questo. Ma se così non fosse, hai ragione. Ho guidato dalla domanda. – Zango

Problemi correlati