¿Cómo se puede hacer referencia a que un objeto dentro de una de sus funciones miembro?
-
05-09-2019 - |
Pregunta
Tengo el siguiente:
var o = {f: function(fn) {
fn.call(o);
}};
var ob = {f: function() {
o.f(function() {
this.x = 2; //HERE: how can this reference ob?
//ob.x = 2;
});
}};
ob.f();
ob.x; // undefined
o.f(fn)
llama fn
donde this
está obligado a o.
En AQUÍ, quiero usar this
acceder a la ob.
Sin embargo, cuando se llama ob.f
, this
está obligado a o
.
JQuery funciona así, creo.
Por ejemplo:
$(...).blah(function() {
this // this is bound to $(...) jquery object.
...
};
Lo que estoy haciendo ahora es:
var Ob = function() {
var self = this;
self.f = function() {
o.f(function() { self.x = 2; };
};
};
var ob = new Ob();
ob.f();
ob.x; // 2
Pero no me gusta anterior por razones estilísticas:
- Uso del operador
new
suena como programación orientada a objetos demasiado clásico. - Definición de
class Ob
usandofunction
no es intuitivo (al menos en principio).
Es por eso que estoy tratando de definir ob
con un objeto literal.
Pero no puedo encontrar una manera de hacer referencia a la ob
objeto en una función
que utiliza llamada a un método que establece this
a otro objeto que ob
.
Puedo hacer algo como lo siguiente:
var ob = {f: function() {
o.f(function() {
self.x = 2;
});
}};
var self = ob;
ob.f();
ob.x;
Pero no sé cómo factorizar anteriormente. Probé:
function obj(o) {
return function() {
var self = o;
return o;
}();
}
var ob = obj({f: function() {
o.f(function() {
self.x = 2;
});
}});
ob.f();
ob.x;// ReferenceError: self is not defined
Por lo tanto, hay una manera de hacer referencia al objeto en una función dentro del objeto
fiable (this
puede obligarse a nada, dependiendo del contexto)?
Solución
Después de Douglas Crockfords patrón simple constructor, me gustaría hacer una función constructora que utiliza el objeto literal en lugar de nuevo. De esta manera:
var o = {f: function(fn) {
fn.call(o);
}};
function obj() {
var me = {};
me.f = function () {
o.f(function() {
me.x = 2;
});
};
return me;
}
var ob = obj();
ob.f();
ob.x; // 2
Otros consejos
En JavaScript, las funciones son objetos, que tiene dos métodos para invocar la función:
call(scope, arg1, arg2, ...);
apply(scope, args); // args is an array of arguments to call the function with
El primer argumento, 'alcance', es el objeto que está unido a 'esto' dentro de la función. Por lo tanto, los siguientes ejemplos son equivalentes:
obj.method(1, 2, 3);
obj.method.call(obj, 1, 2, 3);
obj.method.apply(obj, [1, 2, 3]);
En el primer ejemplo, que está llamando la función pasó a o.f () con 'O' como ámbito de aplicación:
var o = {f: function(fn) {
fn.call(o);
}};
lo tanto, su función pasada en 'ob' referencias 'o' como esto:
var ob = {f: function() {
o.f(function() {
this.x = 2; //HERE: how can this reference ob?
//ob.x = 2;
});
}};
En la línea de 'aquí', 'esto' es en realidad 'o'.
Usted podría intentar lo siguiente:
var ob = {f: function() {
var self = this;
o.f(function() {
self.x = 2; // self is ob now
});
}};
O se podría modificar la función 'o.f' para tomar un parámetro alcance:
var o = {f: function(fn, scope) {
fn.call(scope || this); // Uses the given scope or this (= 'o') if no scope is provided
}};
A continuación, puede pasar a 'esta' en 'ob':
var ob = {f: function() {
o.f(function() {
this.x = 2; // 'this' will be the 'outer' this
}, this); // Here: this as scope
}};
Puede hacerlo sin funciones auxiliares, simplemente usando literales:
var o = {f: function(fn) {
fn.call(o);
}};
var ob = {f: function() {
var self = this; // this == ob
o.f(function() {
self.x = 2; // self == enclosing function's this == ob
});
}};
ob.f();
assert(ob.x == 2);