Javascript: Referencia literal del objeto en la función de la propia clave en lugar de 'esto'

Resuelto Jason asked hace 12 años • 5 respuestas

¿Es problemático hacer referencia a un objeto literal dentro de una función que es parte de ese mismo literal? Parece funcionar bien, pero quiero asegurarme de que no haya otras implicaciones.

Aquí hay un ejemplo de lo que estoy hablando:

en lugar de:

var obj = {
    key1: "it",
    key2: function(){return this.key1 + " works!"}
};
alert(obj.key2());

usando:

var obj = {
    key1: "it",
    key2: function(){return obj.key1 + " works!"}
};
alert(obj.key2());
Jason avatar May 23 '12 05:05 Jason
Aceptado

Ambos pueden ser problemáticos.

var obj = {
    key1: "it",
    key2: function(){ return this.key1 + " works!" }
};
var func = obj.key2;
alert(func()); // error

Cuando funcno se llama como método de obj, thispuede hacer referencia a otra cosa (aquí: el objeto global " window").

var obj = {
    key1: "it",
    key2: function(){ return obj.key1 + " works!" }
};
var newref = obj;
obj = { key1: "something else"; };
alert(newref.key2()); // "something else works"

Aquí accedemos al objeto desde otra referencia, aunque la objfunción ahora puede apuntar a algún otro objeto.

Entonces tendrás que elegir qué caso es más probable. Si realmente desea que sea seguro, evite objque se intercambie:

// ES6 - use `const`:
const obj = {
    key1: "it",
    key2: function(){ return obj.key1 + " works always!" }
};

// ES5: use a closure where the `obj` is stored in a local-scoped variable:
var obj = (function(){
    var local = {
        key1: "it",
        key2: function(){ return local.key1 + " works always!" }
    };
    return local;
})();

o usted bind()la función al objeto:

var obj = {
    key1: "it",
    key2: function(){ return this.key1 + " works always!" }
}
obj.key2 = obj.key2.bind(obj);
Bergi avatar May 22 '2012 22:05 Bergi

Habrá una diferencia en el enlace del alcance variable. Si modifica obj más adelante, modificará el valor de retorno de key2:

var newobj = obj;
obj = { key1: "new" };
alert(newobj.key2());

Ahora alerta "¡nuevos trabajos!", porque aunque estás llamando key2()al objeto original (que es ahora newobj), la referencia a obj.key1ahora se vincula al valor de la nueva objinstancia. El uso thisevita que esto suceda.

Demostración: http://jsfiddle.net/m6CU3/

mellamokb avatar May 22 '2012 22:05 mellamokb

Si no está utilizando un objeto prototipo, puede hacerlo así. ya que todas las instancias de su objeto devolverán el valor de la instancia del obj...

ChristopheCVB avatar May 22 '2012 22:05 ChristopheCVB

Una o ambas técnicas pueden aplicarse dependiendo de la situación.

El valor de thisdentro de una función depende de cómo se llamó la función. Si llamas a una función como propiedad de un objeto como este:

obj.key2();
//or
obj["key2"]();

Entonces thisserá ese objeto. No es relevante si el objeto se creó mediante un literal de objeto o algún otro medio.

Pero puedes usar .call()o .apply()para llamar a una función y establecerla explícitamente thisen algún otro objeto.

Considere también:

var obj = {
    key1: "it",
    key2: function(){return this.key1 + " works!"}
};
alert(obj.key2()); // alerts "it works!"

var func = obj.key2;
alert(func())​;     // alerts "undefined works!"

Estoy configurando funcpara hacer referencia a la misma función que obj.key2, pero llamándola como nofunc() está configurada en .thisobj

Para obtener más información, consulte lo que MDN tiene que decir al respectothis .

nnnnnn avatar May 22 '2012 22:05 nnnnnn