Newsgroup: it.comp.lang.javascript
Titolo: chiedere ad una funzione / metodo qual è il "proprio" this

Il titolo potrà sembrare strano, quindi permettetemi una digressione (e 
correggetemi se ho cannato qualcosa!!!):
 
ogni funzione javascript ha accesso, oltre che ai parametri, a una 
variabile, this, che, in maniera molto prosaica, è sempre avvalorata con l' 
"oggetto prima del punto prima della funzione"
 
ad esempio, se io ho
 
function f() {
  console.log(this);
}
 
window.f()
 
mi farà restituirà l'oggetto window (ok, in strict mode ritorna undefined)
 
se pero' faccio
 
var o = { };
o.f = f;
o.f();
 
mi mostra in console l'oggetto "o".
 
 
questa cosa funziona anche coi prototipi
 
function C() {}
C.prototype.f = f;
var c = new C();
c.f()
 
nel log c'è l'istanza c:
C { f=f()}
 
fin qui abbastanza lineare...
 
Quello che mi servirebbe capire, tuttavia, è se esiste un modo per 
"ispezionare" una variabile per chiederle quale sarebbe stato il suo this...
 
Il mio problema è che questo this "variabile" mi rende molto complicato 
mischiare metodi con funzioni che accettano funzioni come parametro.
 
se io ho
 
function g(p) {
  p();
}
 
g(f);
g(o.f);
g(c.f);
 
in tutt'e tre i casi mi mostra sempre la stessa cosa (window/undefined) 
perché l'"oggetto prima del punto prima della funzione" è perso. Mi serve, 
quindi, ogni volta richiedere esplicitamente quanto dovrebbe valere this e 
usare call / apply per impostarne esplicitamente il valore nella funzione.
 
Nella mia testa la funzione "magica" dovrebbe risalire nello stack di 
chiamate e analizzare il parametro passato... non so se esiste una cosa del 
genere.
 
L'alternativa a passare esplicitamente il this potrebbe essere usare 
.bind(), ma comunque sarebbe un'operazione da fare a monte della chiamata di 
g(), mentre io vorrei comunque qualcosa da fare "a valle", possibilmente 
senza dover toccare f().
 
sapete se esiste una cosa del genere?
 
-- 
ZeD

 senza dover toccare f().
 
Non puoi, come ti ho detto `f` non ha alcun "potenziale `this`": ciò che
passi è il riferimento dell'oggetto function, esattamente come faresti
per un array, sempre. Piú che metodi infatti, in JavaScript, ci sono
"proprietà che puntano a funzioni". Con il `bind` puoi legare una
funzione a un context object specifico (o meglio, creare una funzione da
una funzione che sia legata a un context object specifico), per avere un
comportamento tipo i metodi in altri linguaggi.
 
Considera inoltre che nello strict mode non è possibile neanche risalire
lo stack, questo perché portava a grossi problemi di performance; e
sebbene tu possa provare a implementare qualcosa non in strict mode, o
implementando un tuo transpiler (tanto quelli per js non si contano piú,
ormai); è qualcosa che sconsiglierei.
 
Ignoro le tue motivazioni, ma sembra qualcosa motivato piú dal voler
snaturare il linguaggio per renderlo simile a qualcos'altro che non è;
piuttosto che abbracciare la sua filosofia. Avere funzioni in questo
modo permette un approccio piú orientato alla functional programming.
 
Qual è, se posso chiedere, lo use case specifico?

 Qual è, se posso chiedere, lo use case specifico?
 
beh, veramente il fatto è che vorrei poter definire funzionali...
 
ad esempio nel caso specifico era tutto nato da una funzione "compose(g, f)"
 
inizialmente era una cosa del genere:
 
function compose(g, f) {
    return function () {
        return g.call(undefined, f.apply(undefined, arguments))
    };
}
 
function sum(a, b) {
    return a + b;
}
 
function succ(x) {
    return x + 1;
}
 
var succ_sum = compose(succ, sum);
 
console.log(succ_sum(3, 4)); // 8
 
 
Ma se forzo in .call() e .apply() this=undefined allora devo assicurarmi che 
f e g siano funzioni "pure" indipendenti da this, altrimenti sorgono errori.
 
Posso documentare, ma oltre questo, pero', non posso fare granché, da 
*dentro* la funzione.
 
L'alternativa, ovvio, è mettere il valore "giusto" dei due this... ma per 
fare questo o bisogna cambiare la signature di compose per avere due 
parametri aggiuntivi oppure (e questa era la mia speranza) bisognava fare in 
modo di "calcolarsi" questi due campi da passare a .call() e .apply().
 
Se fosse esistito un motodo del genere mi avrebbe consentito di poter 
gestire in modo trasparente "funzioni pure" e "funzioni che dipendono da 
this".
 
In retrospettiva, non è che avessi tante speranze che un metodo del genere 
esistesse davvero... dopotutto se .call e .apply hanno bisogno di questo 
parametro, invece di poterselo calcolare loro, un motivo doveva pur esserci 
:D
 
Il fatto è che compose(g, f, g_this, f_this) è veramente *brutta* da vedere 
:\
 
-- 
ZeD

 this".
 
Non ti sto seguendo proprio per nulla. :) Non ci sono "funzioni pure" e
"funzioni che dipendono dal `this`" in JavaScript, son tutte la stessa
solfa.
 

 di contesto, e rizzati.
 
Umm, il fatto è, per semplicità, che negli esempi sto sempre usando funzioni 
definite come globali, ma nel mio codice, a meno di casi particolari, sono 
raggruppate in "moduli", e accessibili tramite oggetti. 
 
Ad esempio invece di ``sum()`` e ``succ()`` avrei avuto 
 
(function __math__(window) {
    function sum(a, b) {
        return a + b;
    }
 
    function succ(x) {
        return x + 1;
    }
 
    var math = {};
    math.sum = sum;
    math.succ = succ;
 
    window.math = math;
})(window);
 
(function __func__(window) {
    function compose(g, f) {
        return function () {
            return g.call(undefined, f.apply(undefined, arguments))
        };
    }
 
    var func = {};
    func.compose = compose;
 
    window.func = func;
})(window);
 
questo pero' significa che, scrivendo ``func.compose(math.succ, math.sum)``, 
ho il this del contesto di func.compose che c'entra poco o niente con quello 
di math.succ o math.sum.
Inoltre non potrei sostituire liberamente ``math.succ`` con... boh, 
``console.log``, perché poi, a seconda del browser, potrebbe andare tutto 
bene come potrebbe dare errore.
 
 
Quindi, niente, non mi rimane che, o abbandonare l'idea del compose, oppure 
fare in modo che accetti altri due parametri, con la speranza che vengano 
avvalorati correttamente dal chiamante...
 
 
-- 
ZeD
 

 avvalorati correttamente dal chiamante...
 
Ma cos'hai contro il `bind`? :)