2010-10-26 10 views
8

Quiero hacer esto en Javascript:En referencia a "este" cierre en una matriz en javascript

function Z(f) 
{ 
    f(); 
} 

function A() 
{ 
    this.b = function() 
    { 
    Z(function() { this.c() }); 
    } 

    this.c = function() 
    { 
    alert('hello world!'); 
    } 
} 

var foo = new A(); 
foo.b(); 

Se puede llevar a cabo de esta manera:

function Z(f) 
{ 
    f(); 
} 

function A() 
{ 
    var self = this; 
    this.b = function() 
    { 
    Z(function() { self.c() }); 
    } 

    this.c = function() 
    { 
    alert('hello world!'); 
    } 
} 

var foo = new A(); 
foo.b(); 

¿Hay una mejor manera?

Respuesta

6

Mantener una referencia a la matriz (como que tiene) es un buen enfoque, sin embargo, para el ejemplo específico que no hay necesidad de que el envoltorio en el anonimato, puede pasar directamente a la función, así:

var self = this; 
this.b = function() 
{ 
    Z(self.c); 
} 

You can test it out here, y sin este envoltorio no hay realmente ninguna necesidad de que la variable self, sólo puede utilizar this directamente como aquí:

this.b = function() 
{ 
    Z(this.c); 
} 

You can test that version here.


Dado que parece que hay cierta confusión en los comentarios a continuación, el código anterior mantiene thispara la pregunta, si se quiere mantener la this/contexto dentro de la devolución de llamada, así, utilizar .call()like this:

this.b = function() 
{ 
    Z.call(this, this.c); 
} 

Y para Z:

function Z(f) 
{ 
    f.call(this); 
} 

You can test it here.

+0

derecho, en este ejemplo sencillo, no hay ninguna razón por la envoltura. No debería ser difícil concebir un ejemplo donde sea necesario. (Cambiando parámetros, etc.) Sin embargo, si no se ajusta, ¿supongo que el cierre se pasa como uno podría esperar? –

+2

sin el contenedor anónimo, se llama 'c' con la referencia' this' incorrecta. – Lee

+0

@Jonathan - Sí, correcto, en ese caso, querrá pasar una variable tal como usted tiene 'self' que le permite acceder a lo que está en el cierre. –

1

Hay un patrón que a menudo se denomina "Delegar", que soluciona este problema.

en JavaScript, una aplicación no muy elegante podría ser algo como esto:

/** class Delegate **/ 
var Delegate = function(thisRef, funcRef, argsArray) { 
    this.thisRef=thisRef; 
    this.funcRef=funcRef; 
    this.argsArray=argsArray; 
} 
Delegate.prototype.invoke = function() { 
    this.funcRef.apply(this.thisRef, this.argsArray); 
} 
/** static function Delegate.create - convenience function **/ 
Delegate.create = function(thisRef, funcRef, argsArray) { 
    var d = new Delegate(thisRef, funcRef, argsArray); 
    return function() { d.invoke(); } 
} 

En su ejemplo, se usaría así:

this.b = function() { 
    Z(Delegate.create(this, this.c)); 
} 

también se puede escribir funciones que esperan recibir un Delegado:

function Z(d) { 
    d.invoke(); 
} 

luego, en A, su impl de b se convierte en:

this.b = function() { 
    var d = new Delegate(this, this.c); 

    Z(d); 
    SomeOtherFunc(d); 
} 

El Delegate simplemente proporciona una manera simple y consistente de encapsular la referencia this (que usted ha llamado self), dentro de una instancia de objeto que puede ser tratada como cualquier otra instancia de objeto. Es más legible y evita tener que contaminar el alcance de su función con variables superfluas como self. Una implementación delegada más elegante podría tener sus propios métodos y otro estado relacionado. También es posible construir el delegado de tal manera que ayude a minimizar algunos problemas de administración de memoria relacionados con el alcance (aunque el código que he mostrado aquí definitivamente no es un ejemplo de eso).

+0

No creo que esto funcione: 'Z (function() {Delegate.create (this, c)});'. Sin el contenedor, no hay necesidad de 'self' ni ninguna razón para el Delegate porque es más corto escribir 'Z (this.c);'. –

+0

@Jonathan: has agregado un contenedor adicional que no está en mi ejemplo. es solo 'Z (Delegate.create (this, c))'; Amplié un poco el ejemplo de Delegado para que sea más flexible y más claro lo que está pasando. – Lee

+0

@Jonathan - 'Z (this.c)' funcionará, siempre y cuando no te importe a qué objeto 'this' hace referencia cuando se ejecuta dentro de' c'. El código que has mostrado no usa 'this' dentro de' c', por lo que no presentará ningún problema. Si realiza el check-out (esta ligera modificación del ejemplo de @ Nick) [http://jsfiddle.net/UQpnX/], verá el problema potencial, que se resuelve mediante el contenedor anónimo, en su ejemplo original, o con una construcción más formal como el Delegado. Cualquiera está bien. – Lee

1

alternativa, puede utilizar

this.b = function() 
{ 
    Z((function() { this.c() }).apply(this)); 
} 
Cuestiones relacionadas