2011-12-13 14 views
5

Ho questo codice (JSFiddle)Come posso adattare correttamente questo metodo "pubblico"?

var OBJ = function(){ 
    var privateVar = 23; 
    var self = this; 

    return { 
     thePrivateVar : function() { 
      return privateVar; 
     }, 

     thePrivateVarTimeout : function() { 
      setTimeout(function() { alert(self.thePrivateVar()); } , 10); 
     } 
    } 

}(); 

alert(OBJ.thePrivateVar()); 

OBJ.thePrivateVarTimeout(); 

Questa è un'astrazione di un vero problema che sto avendo.

Così - mi si aspetterebbe la chiamata a OBJ.thePrivateVarTimeout() aspettare 10 e poi alert con 23 (che voglio che l'accesso attraverso l'altro metodo esposto).

Tuttavia, l'impostazione self non sembra essere impostata correttamente. Quando sto impostando self = this sembra che this non sia un riferimento alla funzione ma un riferimento all'oggetto globale. Perchè è questo?

Come è possibile impostare il metodo pubblico thePrivateVarTimeout l'altro metodo pubblico thePrivateVar?

+2

* Perché è questo? * Poiché si sta chiamando la funzione normalmente ('func()'). In questo caso, 'this' fa sempre riferimento all'oggetto globale. Se vuoi che si riferisca ad un oggetto vuoto, chiamalo con 'new' o assegnane uno:' var self = {}; '. –

+0

@FelixKling Grazie rende "self" impostato correttamente. Non riesco ancora a usarlo per invocare 'thePrivateVar'. Penso che la risposta di Raynos sia il modo in cui dovrei farlo. –

risposta

5
var OBJ = (function(){ 
    var privateVar = 23; 
    var self = { 
     thePrivateVar : function() { 
      return privateVar; 
     }, 

     thePrivateVarTimeout : function() { 
      setTimeout(function() { alert(self.thePrivateVar); } , 10); 
     } 
    }; 

    return self; 

}()); 

this === global || undefined all'interno di una funzione chiamata. In ES5 è qualunque sia l'ambiente globale, in ES5 rigoroso non è definito.

modelli più comuni comporterebbe utilizzando il var that = this come valore locale in una funzione di

var obj = (function() { 
    var obj = { 
    property: "foobar", 
    timeout: function _timeout() { 
     var that = this; 
     setTimeout(alertData, 10); 

     function alertData() { 
     alert(that.property); 
     } 
    } 
    } 

    return obj; 
}()); 

o utilizzando un metodo .bindAll

var obj = (function() { 
    var obj = { 
    alertData: function _alertData() { 
     alert(this.property); 
    } 
    property: "foobar", 
    timeout: function _timeout() { 
     setTimeout(this.alertData, 10); 
    } 
    } 

    bindAll(obj) 

    return obj; 
}()); 


/* 
    bindAll binds all methods to have their context set to the object 

    @param Object obj - the object to bind methods on 
    @param Array methods - optional whitelist of methods to bind 

    @return Object - the bound object 
*/ 
function bindAll(obj, whitelist) { 
    var keys = Object.keys(obj).filter(stripNonMethods); 

    (whitelist || keys).forEach(bindMethod); 

    function stripNonMethods(name) { 
     return typeof obj[name] === "function"; 
    } 

    function bindMethod(name) { 
     obj[name] = obj[name].bind(obj); 
    } 

    return obj; 
} 
+0

Grazie, ho usato il primo modello. Non ho davvero bisogno di "io" per essere un riferimento all'OBJ generale - Ho solo bisogno dei metodi pubblici per potermi chiamare l'un l'altro. Tuttavia, anche Felix ha affrontato il problema di "sé". –

+0

@ElRonnoco Personalmente preferisco il pattern '.bindAll' perché' that = this' mi fa sanguinare gli occhi. – Raynos

+1

@Raynos nella riga 'pd.bindAll (obj)' cosa è 'pd' o da dove viene il pd? –

Problemi correlati