2011-02-15 11 views
5

tengo componentes de JavaScript, que ha siguiente arquitectura:Este puntero de función interna

var MyComponent = function(params) 
{ 
    setup(params); 


    this.doSomething() 
    { 
     // doing something 
    }; 

    function setup(params) 
    { 
     // Setup 

     // Interaction logic 
     var _this = this; // "this" points to DOMWindow, not to created object 
     $(".some-element").click(function(){ 
      _this.doSomething(); // it craches here, because of above 
     }); 
    } 
}; 

Cuando algo, siendo controlado por la lógica de interacción, ocurre, a veces tengo que remitir a los métodos de ejecución "públicas" de los componentes.

En esta situación, tengo un problema con "este" puntero.

Código de ejemplo demuestra que:

var Item = function() 
{ 
    this.say = function() 
    { 
     alert("hello"); 
    }; 
    this.sayInternal = function() 
    { 
     _sayInternal(); 
    }; 
    function _sayInternal() 
    { 
     this.say(); 
    }; 
}; 

Para probarlo,

  • crear un objeto:

var o = new Item();

  • Esto funciona bien:

o.say(); // alerts "hello"

  • Este accidentes:

o.sayInternal();

Me aparece un error:

TypeError: Result of expression 'this.say' [undefined] is not a function.

pienso, tal comportamiento tiene lugar, porque _sayInternal () la función es declarada (y no asignada al objeto, como "this.say = function()"). De esta forma, se comparte entre todos los objetos creados y actúa como una función estática en C++.

¿Es esto cierto?

Respuesta

3

No, sayInternal no se comparte entre los objetos creados. Pero tiene razón, los objetos creados no tienen acceso a sayInternal ya que no están asignados a ellos. Esta función es solo local para la función constructora.

this siempre se refiere al contexto se invoca una función. Si usted lo llama como func(), entonces this se refiere al objeto global (que es window en el navegador). Si configura la función como propiedad de un objeto y la llama con obj.func(), entonces this se referirá a obj.

Si asigna una función "obligado" a una variable y lo llaman:

var method = obj.func; 
method(); 

continuación this volverá a hacer referencia al objeto global. En JavaScript, las funciones son como cualquier otro valor, no tienen una relación especial con el objeto al que están asignadas.


Puede establecer explícitamente el contexto con call o apply:

var MyComponent = function(params) 
{ 
    setup.call(this, params); // <- using `call` 

    this.doSomething() 
    { 
     // doing something 
    }; 

    function setup(params) 
    { 
     // Setup 
     // Interaction logic 
     var _this = this; // "this" to new created object 
     $(".some-element").click(function(){ 
      _this.doSomething(); 
     }); 
    } 
}; 

o en que otro ejemplo:

var Item = function() 
{ 
    this.say = function() 
    { 
     alert("hello"); 
    }; 
    this.sayInternal = function() 
    { 
     _sayInternal.call(this); 
    }; 
    function _sayInternal() 
    { 
     this.say(); 
    }; 
}; 

Dicho esto, este enfoque para asignar funciones a los objetos no son buenos, porque cada instancia tendrá su propio this.sayInternal función. Por lo tanto, para el código Item anterior, cada creación de una instancia también implica la creación de tres funciones, lo cual es una pérdida de memoria.

haciendo uso de prototype inheritance sería una mejor manera:

var Item = function() { 
}; 

Item.prototype = (function() { 
    function _sayInternal() { 
     this.say(); 
    }; 

    return { 
     say: function() { 
      alert("hello"); 
     }, 
     sayInternal: function(){ 
      _sayInternal.call(this); 
     } 
    } 
}()); 

De esta manera, _sayInternal sólo se crea vez y todas las instancias heredan (consulte) el prototipo, por lo say y sayInternal también existen solamente una vez . El "truco" con la función inmediata hace que _sayInternal solo esté accesible por say y sayInternal.

+0

Gracias! Gran explicación! – AntonAL

Cuestiones relacionadas