2009-10-08 9 views
25

Estoy tratando de entender por qué en javascript, es posible que desee cambiar el contexto de una función. Estoy buscando un ejemplo del mundo real o algo que me ayude a entender cómo/por qué se usa esta técnica y cuál es su significado.Cómo cambiar el contexto de una función en javascript

La técnica se ilustra mediante este ejemplo (de http://ejohn.org/apps/learn/#25)

var object = {}; 
function fn(){ 
    return this; 
} 
assert(fn() == this, "The context is the global object."); 
assert(fn.call(object) == object, "The context is changed to a specific object."); 
+13

Funny; Encontré esta página porque necesito establecer el contexto para una llamada que estoy realizando y no recuerdo la sintaxis ... :) – rinogo

+1

+1 debe titularse: "Cómo cambiar el contexto de una función en javascript" (jk - gracias por publicar esto!) –

+0

+1 Estaba buscando cómo mantener esto coherente dentro de una clase ... – LoremIpsum

Respuesta

20

jQuery hace uso de ella con buenos resultados:

$('a').each(function() { 
    // "this" is an a element - very useful 
}); 

El código real jQuery se ve así:

for (name in object) { 
    if (callback.call(object[ name ], name, object[ name ]) === false) { 
     break; 
    } 
} 

Si simplemente lo hizo callback(name, object[ name ]) entonces this no se establecería en el objeto actual en su iterador y, en su lugar, tendría que usar el parámetro. Básicamente solo hace las cosas más fáciles.

+2

Para que quede claro, el primer parámetro para '.call()' se convierte en 'this'. Más detalles @ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call – EpicVoyage

6

Por favor, echar un vistazo a este ejemplo:

<script> 
var el = document.getElementById('button'); 
el.onclick = function(){ 
    this.value = "Press Me Again"; //this --> now refers to the the element button not on the window 
} 

//Another Example: 
var Person = function(name,location){ 
    this.name = name; 
    this.location = location; 
    alert(this.location); 
} 
var p2 = new Person("Samantha","California"); //this refers to the instance of the function Person(Person now acts as a class) 
var p1 = Person(); // this refers to the window(Person simply acts as a simple function) 
</script> 
<button id="button1">Press Me</button> 

La nueva palabra clave cambia el contexto.

3

Es muy útil cuando se hace devoluciones de llamada de peticiones AJAX:

function Person(_id, _name) { 
    this.id = _id; 
    this.name = _name; 
}; 

Person.prototype.sayHi = function(greeting) { 
    alert(greeting + " from " + this.name); 
}; 

Person.prototype.loadFromAJAX = function(callback) { 
    // in this example, it's jQuery, but could be anything 
    var t = this; 
    $.get("myurl.php", function(data) { 
     callback.call(t, data.greeting); 
    }); 
}; 

En realidad, eso es un ejemplo bastante malo.

Hay toneladas de usos en jQuery. . Por ejemplo, el jQuery() Obtiene la función():

get: function(num) { 
    return num === undefined ? 
     // Return a 'clean' array 
     Array.prototype.slice.call(this) : 
     // Return just the object 
     this[ num ]; 
} 

Se trata de utilizar las funciones del prototipo de matriz, pero en el contexto del objeto jQuery.

3

Un ejemplo del mundo real que he encontrado:

Si se agrega una función como un controlador de eventos a un elemento DOM y si se utiliza "este" dentro de esa función, "este" se referirá a la DOM elemento al que ha agregado el controlador de eventos.

Pero esa función puede ser un método de un objeto y desea que la palabra clave "this" usada en su interior haga referencia al objeto propietario ... por lo que debe cambiar el contexto para que "este" no consulte el elemento DOM , pero se referirá al objeto propietario .

Puede cambiar fácilmente el contexto de una función en jquery utilizando la función proxy(). Ver esta pregunta: jquery "this" binding issue on event handler (equivalent of bindAsEventListener in prototype) y la primera respuesta

0

siempre me encuentro en la necesidad de tener contexto diferente al utilizar setTimeout y jQuery tiene una función muy útil $.proxy la que hace el truco:

function iAmCalledAfterTimeout() 
{ 
    alert(this.myProperty); //it will alert "hello world" 
}  

setTimeout($.proxy(iAmCalledAfterTimeout, {myProperty:"hello world"}), 1000); 
1

se unen función puede ser lo que estás buscando, la función de vinculación devuelve una nueva función en el contexto que pasaste, un escenario de mundo real podría ser cuando estás usando delegados de jquery para adjuntar algún comportamiento a un elemento dom, y quieres el la devolución de llamada se ejecuta en un contexto diferente. porque el contexto predeterminado en un jquery delgate es el objeto dom que está vinculado al manejador, lo que significa que no puede acceder a ninguna propiedad además de las propiedades que pertenecen al objeto dom

Cuestiones relacionadas