I am trying to take an OOP approach in javascript by following this and the one on the mozilla website . When I instantiate my function/class with the new
keyword the graph renders correctly, however when a this variable is passed into a callback function it becomes undefined
, I was wondering if there was a way around this?
Here is my code:
function lineBasedCharts (renderTo, chartType, deviceID, metricType, refreshCycle, title, subtitle, yAxis, tooltip) {
this.mRenderTo = renderTo
this.mRefreshCycle = refreshCycle
this.mChartType = chartType
this.mTitle = title
this.mSubtitle = subtitle
this.mYAxis = yAxis
this.mTooltip = tooltip
...
this.chart = new Highcharts.Chart(options, function (ch) {
//use a callback function off the end of highcharts, for when the chart has fully loaded.
AddSeries(ch, deviceID, metricType);
if (ch.series[0].data.length > 0) {
setTimeout(requestData, this.mRefreshCycle, ch, ch.series[0].data[ch.series[0].data.length - 1].x, deviceID, metricType, this.mRefreshCycle);
}
});
}
and this is how I instantiate my object
var chart = []
chart.push(new lineBasedCharts('lineChart', 'spline', 49, 'TEMP', 30000, 'temp', 'Temp in degrees', 'Temperature (°C)', '°C'))
this.mRefreshCycle
seems to be become undefined when used in the callback function.
Pass refreshCycle
as argument to setTimeout
instead. It is always dangerous to use this
since it changes meaning dependent upon context.
this
is most likely referring to your created Highcharts.chart
object. Create an alias of this (_this = this)
and try use _this.mRefreshCycle
function lineBasedCharts (renderTo, chartType, deviceID, metricType, refreshCycle, title, subtitle, yAxis, tooltip) {
//Add alias for this
_this = this;
this.mRenderTo = renderTo
this.mRefreshCycle = refreshCycle
this.mChartType = chartType
this.mTitle = title
this.mSubtitle = subtitle
this.mYAxis = yAxis
this.mTooltip = tooltip
...
this.chart = new Highcharts.Chart(options, function (ch) {
//use a callback function off the end of highcharts, for when the chart has fully loaded.
AddSeries(ch, deviceID, metricType);
if (ch.series[0].data.length > 0) {
//change how you refer to mRefreshCycle
setTimeout(requestData, _this.mRefreshCycle, ch, ch.series[0].data[ch.series[0].data.length - 1].x, deviceID, metricType, this.mRefreshCycle);
}
});
}
The scope of 'this' within the callback function is likely the "new Highcharts.Chart", not the "lineBasedChart" function. It has no idea what mRefreshCycle is because it does not exist within the scope of the newly created object. You might be able to just remove the 'this' and take advantage of the closure mechanism.
Also, the "options" being passed to the "new Highcharts.Chart()" are undefined.
Sending this from my phone. I apologize for lack of markdown. I will update the format of answer when I get a chance.
As others have suggested, I would remove the "this" identifier and use the parameter that is being passed in. They're the same value at this point anyway, as long as you haven't changed the value of mRefreshCycle at a later time. If you have a mutator that does this then you will need to tweak this slightly.
How about making lineBasedChart an actual object?
var LineBasedChart = function (renderTo, chartType, deviceID, metricType, refreshCycle, title, subtitle, yAxis, tooltip) {
var self = this;
this.mRenderTo = renderTo
this.mRefreshCycle = refreshCycle
this.mChartType = chartType
this.mTitle = title
this.mSubtitle = subtitle
this.mYAxis = yAxis
this.mTooltip = tooltip
...
this.chart = new Highcharts.Chart(options, function (ch) {
//use a callback function off the end of highcharts, for when the chart has fully loaded.
AddSeries(ch, deviceID, metricType);
if (ch.series[0].data.length > 0) {
setTimeout(requestData, self.mRefreshCycle, ch, ch.series[0].data[ch.series[0].data.length - 1].x, deviceID, metricType, self.mRefreshCycle);
}
});
/*Mutator to update refresh cycle value*/
this.setRefreshCycle = function(refreshCycle) {
this.mRefreshCycle = refreshCycle;
}
}
This would be useful if you're creating multiple objects eg
var lineBasedChart1 = new LineBasedChart(...)
var lineBasedChart2 = new LineBasedChart(...)
You don't necessarily need to use a mutator you could just call on the property directly.
lineBasedChart1.mRefreshCycle = 500;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.