2012-05-23 21 views
13

tengo esta clase:Javascript acceso función privada variable pública

function ctest() { 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2(); 
     alert(this.var1); 
    } 
    var func2 = function() { 
     this.var1 = "huhu"; 
    } 
} 

y llamo:

var myobj = new ctest(); 
    myobj.func1(); 

no se supone que la segunda alerta pop-up "huhu"? func2 es privado, ¿no puede acceder a la variable pública var1?

si una función privada no puede acceder a una variable pública, ¿cómo puedo hacerlo?

¡Gracias de antemano!

+2

Además, no hay tal cosa como 'privado' aquí. – Alexander

+0

Este 'obj.func1()' probablemente debería ser 'myobj.func1()' – forsvarir

+0

@forsvarir, sí, debería - Lo arreglé para él. – Alnitak

Respuesta

17

necesita proporcionar un contexto para la llamada a func2:

this.func1 = function() { 
    alert(this.var1); 
    func2.call(this); 
    alert(this.var1); 
} 

Sin el contexto de la llamada va a utilizar el objeto global (es decir window) - usted debe ver cuando se ejecuta el código actual que window.var1 es creando entre las dos alertas.

+0

si hago lo que sugirió dice que func2() no es una función – MIrrorMirror

+0

@MIrrorMirror ah, umm, sí, ¡espera! – Alnitak

+0

@Alnitak Por favor, lea su código, func2 no es una función pública. – xdazz

0
function ctest() { 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2(this); 
     alert(this.var1); 
    } 
    var func2 = function(obj) { 
     obj.var1 = "huhu"; 
    } 
} 

Y no hay otra manera de resolver este problema, compruebe las otras respuestas :)

+0

El infractor debería darte tu razón. – xdazz

+0

@Alnitak Pero eso no será un problema, 'obj' es el parámetro. – xdazz

12

funciones no están vinculados a casos, por lo tanto, su invocación de func2 termina como invocación sin this que apunta a la instancia esperada .

Usted puede fijar la invocación para que incluya el contexto:

function ctest() { 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2.call(this); 
     alert(this.var1); 
    } 
    var func2 = function() { 
     this.var1 = "huhu"; 
    } 
} 

O puede mantener una variable con la referencia del objeto deseado en torno a:

function ctest() { 
    var that = this; 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2(); 
     alert(this.var1); 
    } 
    var func2 = function() { 
     that.var1 = "huhu"; 
    } 
} 
+0

gracias! esto me ayudó mucho –

+0

¿Puede proporcionar más información sobre este tema, ya que quiero saber cuál es la mejor práctica y por qué – InsOp

+1

@InsOp? Sugiero leer la ayuda de MDN sobre la palabra clave "this": https: //developer.mozilla.org/es-ES/docs/Web/JavaScript/Reference/Operators/this – Lucero

2

Otra opción es utilizar Function.bind:

function ctest() { 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2(); 
     alert(this.var1); 
    } 
    var func2 = function() { 
     this.var1 = "huhu"; 
    }.bind(this); 
} 

Tenga en cuenta que la compatibilidad con el navegador para esto no es perfecta.

+0

¿Por qué usar 'that' _and_' .bind() 'al mismo tiempo? – Alnitak

+0

@Alnitak: mala copia y pegado – Eric

2

No existe nada privado en JS, pero puede jugar con ámbitos utilizando closures.

Digamos por ejemplo que en su ejemplo no necesita exponer var1 como propiedad pública. Desde aquí se puede reescribir su código mientras que sigue:

function ctest() { 
    var var1 = "haha"; 

    this.func1 = function() { 
     alert(var1); 
     func2(); 
     alert(var1); 
    } 

    var func2 = function() { 
     var1 = "huhu"; 
    } 
} 

Debido a que tanto func1 y func2 comparte el mismo alcance - que se definen en la misma función, ctest - que pueden tener acceso a las mismas variables. Por supuesto, en ese caso no tiene var1 expuesto, entonces: myobj.var1 será undefined.

Si desea var1 a ser expuesto como una propiedad, entonces lo que necesita es bindfunc2 a la instancia del objeto que ha creado en el constructor:

function ctest() { 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2(); 
     alert(this.var1); 
    } 
    var func2 = function() { 
     this.var1 = "huhu"; 
    }.bind(this); 
} 

De lo contrario func2 tendrá un objeto de contexto diferente (this). Si el navegador no soporta bind y no desea utilizar una cuña (como se muestra en el siguiente enlace), se puede tomar ventaja de los cierres de nuevo:

function ctest() { 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2(); 
     alert(this.var1); 
    } 
    var context = this; 
    var func2 = function() { 
     context.var1 = "huhu"; 
    } 
} 

IMVHO es menos elegante.

Cuestiones relacionadas