JavaScript-Dueño de "esto"
class methods (5)
Seguí un tutorial para crear un cronómetro de JavaScript y estoy tratando de expandirlo para que funcione con múltiples cronómetros (múltiples instancias de una clase). El problema que tengo es cuando estoy tratando de mostrar el valor actual mientras el tiempo corre. Necesito codificar la instancia de la clase porque "this" no funciona (en la línea donde estoy usando console.log). Corté el código al mínimo para tratar de entender este aspecto y pegué lo que tengo a continuación:
function Timer(){
var time1 = null;
var time2 = null;
var timeLoop = null;
function getTime(){
var day = new Date();
return day.getTime();
}
this.start = function(){
time1 = getTime();
timeLoop = setInterval(function(){
time2 = getTime();
console.log(_Timer.duration());
//console.log(this.duration());
},500);
}
this.duration = function(){
return (time1 - time2) / 1000;
}
}
Creo que el siguiente enlace describe mi problema, pero no lo entiendo lo suficiente como para aplicarlo aquí. ¿El problema se debe a que el propietario sea este. Comience en lugar de solo esto y cómo puedo modificar el código para que funcione con cualquier instancia de Timer?
http://www.quirksmode.org/js/this.html
He incluido tanto la línea de valor codificado duro como la línea "this" que no funciona.
Gracias,
Geraint
Cada vez que vea la function
, puede asumir el valor de this
cambios, por lo que dentro de la función de devolución de llamada para el intervalo, this
es realmente la window
, no el objeto.
La solución fácil es simplemente almacenar this
en una variable
function Timer(){
var time1 = null;
var time2 = null;
var timeLoop = null;
function getTime(){
var day = new Date();
return day.getTime();
}
this.start = function(){
var self = this;
time1 = getTime();
timeLoop = setInterval(function(){
time2 = getTime();
console.log(self.duration());
},500);
}
this.duration = function(){
return (time1 - time2) / 1000;
}
}
Lo primero es lo primero. Javascript no es compatible con POO basado en clases. Es OOP junto con su herencia es prototípico.
A continuación se muestra un ejemplo de cómo implementar las características del prototipo de OOP con su ejemplo de temporizador:
function Timer(){
var time1 = null;
var time2 = null;
var timeLoop = null;
}
Timer.prototype.getTime = function(){
var day = new Date();
return day.getTime();
}
Timer.prototype.start = function(){
time1 = this.getTime();
timeLoop = this.setInterval(function(){
time2 = this.getTime();
console.log(this.duration());
}.bind(this),500);
}
Timer.prototype.duration = function(){
return (time1 - time2) / 1000;
}
Mire la sección Objetos personalizados de la reintroducción de Javscript de MDN
No hay nada malo con la forma en que se muestra en tu tutorial. Es solo que esta es una forma más limpia y la llamada de bind
solo es necesaria para la sentencia console.log
que de lo contrario asociaría this
como la window
. Si te deshaces de él, puedes deshacerte del bind
también.
Si desea que la propiedad this
sea coherente, debe vincular las funciones que se están llamando.
Por ejemplo,
setInterval(function() { /* code here */ }.bind(this), 500)
De esta forma, el de la función interna será el mismo que el de la función externa.
Tratar:
function Timer(){
var time1 = null;
var time2 = null;
var timeLoop = null;
var _this = this;
function getTime(){
var day = new Date();
return day.getTime();
}
this.start = function(){
time1 = getTime();
timeLoop = setInterval(function(){
time2 = getTime();
console.log(_this.duration());
},500);
}
this.duration = function(){
return (time1 - time2) / 1000;
}
}
this
no es una variable local, por lo que no se guarda en cierres. Debe asignar una variable local:
this.start = function(){
var self = this;
time1 = getTime();
timeLoop = setInterval(function(){
time2 = getTime();
console.log(self.duration());
},500);
}