Javascript 变量坚持使用最后一个值覆盖第一个值
Javascript variable sticks with the last value overriding the first ones
我有显示 google 图表的功能。我想显示存储在数据库中的每一年的图表。
几个小时以来我一直困扰的问题是,例如,变量
var year
始终将最后一年作为值。
例如,如果我想显示每年(2013 年和 2014 年)的图表,它只会显示 2014 年的图表,而忽略第一年。如果我只得到2013年的数据,它显示的是2013年的数据。
好像覆盖了所有数据,只保留最后一个值
我的代码如下:
<?php
foreach ($anios as $anio)
{
?>
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
<?php
$datos=$difusion_stats->notas_stats_anio($anio->Año);
?>
var year=<?=$anio->Año?>; console.log('First, the year value is '+year);
var data=<?=$datos?>;
var id_chart = 'chart_'+<?=$anio->Año?>;
function drawChart() {
console.log('Inside the drawChart() function. Current year value is: '+year);
console.log('Php current year value is: '+<?=$anio->Año?>);
var data = google.visualization.arrayToDataTable(<?=$datos?>);
var options = {
title: 'Distribución de notas y entrevistas en el año '+<?=$anio->Año?>,
legend: 'Porcentaje de los distintos tipos de eventos',
pieSliceText: 'texto',
slices : {
0 : {offset: 0.1}
},
/*sliceVisibilityThreshold: .2,//Para contraer el resto y poner "otro"*/
pieHole: 0.4,
backgroundColor: { fill:'transparent'},
tooltip: {showColorCode: true},
tooltip: {isHtml: true},
height: 400,
titleTextStyle: {
color: '#FFFFFF'
},
legendTextStyle: {
color: '#FFFFFF'
}
};
var chart = new google.visualization.PieChart(document.getElementById(id_chart));
chart.draw(data, options);
/*Para hacerlo responsive:
function resizeHandler () {
chart.draw(data, options);
}
if (window.addEventListener) {
window.addEventListener('resize', resizeHandler, false);
}
else if (window.attachEvent) {
window.attachEvent('onresize', resizeHandler);
}
}/*Fin de la función drawChart()*/
</script>
<?php
}/*Fin del foreach PHP*/
?>
在这种情况下,生成的 javascript 代码是每年的两个代码:2013 年和 2014 年:
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
var year=2013; console.log('First, the year value is '+year);
var data=[['tipo','Cantidad'],['nota',14],['entrevista',3]];
var id_chart = 'chart_'+2013;
function drawChart() {
console.log('Inside the drawChart() function. Current year value is: '+year);
console.log('Php current year value is: '+2013);
var data = google.visualization.arrayToDataTable([['tipo','Cantidad'],['nota',14],['entrevista',3]]);
var options = {
title: 'Distribución de notas y entrevistas en el año '+2013,
legend: 'Porcentaje de los distintos tipos de eventos',
pieSliceText: 'texto',
slices : {
0 : {offset: 0.1}
},
/*sliceVisibilityThreshold: .2,//Para contraer el resto y poner "otro"*/
pieHole: 0.4,
backgroundColor: { fill:'transparent'},
tooltip: {showColorCode: true},
tooltip: {isHtml: true},
height: 400,
titleTextStyle: {
color: '#FFFFFF'
},
legendTextStyle: {
color: '#FFFFFF'
}
};
var chart = new google.visualization.PieChart(document.getElementById(id_chart));
chart.draw(data, options);
/*Para hacerlo responsive:
function resizeHandler () {
chart.draw(data, options);
}
if (window.addEventListener) {
window.addEventListener('resize', resizeHandler, false);
}
else if (window.attachEvent) {
window.attachEvent('onresize', resizeHandler);
}
}/*Fin de la función drawChart()*/
</script>
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
var year=2014; console.log('First, the year value is '+year);
var data=[['tipo','Cantidad'],['nota',43],['entrevista',12]];
var id_chart = 'chart_'+2014;
function drawChart() {
console.log('Inside the drawChart() function. Current year value is: '+year);
console.log('Php current year value is: '+2014);
var data = google.visualization.arrayToDataTable([['tipo','Cantidad'],['nota',43],['entrevista',12]]);
var options = {
title: 'Distribución de notas y entrevistas en el año '+2014,
legend: 'Porcentaje de los distintos tipos de eventos',
pieSliceText: 'texto',
slices : {
0 : {offset: 0.1}
},
/*sliceVisibilityThreshold: .2,//Para contraer el resto y poner "otro"*/
pieHole: 0.4,
backgroundColor: { fill:'transparent'},
tooltip: {showColorCode: true},
tooltip: {isHtml: true},
height: 400,
titleTextStyle: {
color: '#FFFFFF'
},
legendTextStyle: {
color: '#FFFFFF'
}
};
var chart = new google.visualization.PieChart(document.getElementById(id_chart));
chart.draw(data, options);
/*Para hacerlo responsive:
function resizeHandler () {
chart.draw(data, options);
}
if (window.addEventListener) {
window.addEventListener('resize', resizeHandler, false);
}
else if (window.attachEvent) {
window.attachEvent('onresize', resizeHandler);
}
}/*Fin de la función drawChart()*/
</script>
但从未显示 2013 年的图表。 :/
在这种情况下,我得到两年:2013 年和 2014 年。但是,在控制台日志消息中,我看到它通过替换为去年来覆盖 2013 年,因此消息是:
First, the year value is 2013
stats:273 After calling the setOnLoadCallback() function, the year value is 2013
stats:274 we are about to call the drawChart() function ... YEAR: 2013
stats:280 First, the year value is 2014
stats:286 After calling the setOnLoadCallback() function, the year value is 2014
stats:287 we are about to call the drawChart() function ... YEAR: 2014
**stats:290 Inside the function. Current year value is: 2014**
stats:290 Inside the function. Current year value is: 2014
2013的值被2014覆盖了,为什么会这样?
我该如何解决这个问题?
在您的代码中,您已经定义了函数 draw_chart twice.Instead 您应该定义它一次,并在 2013 年和 2014 年使用不同的参数调用它两次。
您的第二个脚本标签包含 2014 年图表的代码,覆盖 2013 年,因此它只显示 2014 年
我不知道 PHP 但问题可能出在这一行 var id_chart = 'chart_'+<?=$anio->Año?>;
。所以试试 console.log(id_chart);
。如果每次都打印不同,那么它应该绘制两个不同的图表,具体取决于该元素是否存在于 DOM 中。否则
尝试改变
var chart = new google.visualization.PieChart(document.getElementById(id_chart));
到
var span=document.createElement('span');
document.getElementById(id_chart).appendChild(span);
var chart = new google.visualization.PieChart(span);
var year
在这两种情况下都被写入全局 JS 范围。当 drawChart
函数为 运行 时,两个 var year
命令都已为 运行,因此使用 2014 年。
它将帮助您将问题减少到更小的代码集,您将看到会发生什么:
<script type="text/javascript">
google.setOnLoadCallback(drawChart);
var year=2013; console.log('First, the year value is '+year);
function drawChart() {
console.log('Inside the drawChart() function. Current year value is: '+year);
console.log('Php current year value is: '+2013);
}
script>
<script type="text/javascript">
google.setOnLoadCallback(drawChart);
var year=2014; console.log('First, the year value is '+year);
function drawChart() {
console.log('Inside the drawChart() function. Current year value is: '+year);
console.log('Php current year value is: '+2014);
}/*Fin de la función drawChart()*/
</script>
- 它为一个名为
drawChart
的函数调用了setOnLoadCallback,这个函数还不存在(但是JavaScript中的声明是"hoisted",换句话说,后面的function drawChart
被认为存在于范围的顶部,因此它有效。)
- 然后设置
year = 2013
.
- 然后定义了drawChart的日志语句说PHP年是2013年(因为这段代码变成了静态JS代码)以及JS的current值是多少var
year
是.
- 然后它再次为
drawChart
调用 setOnLoadCallback。
- 然后设置
year = 2014
。这在技术上是不正确的 JS,因为它使用 var
作为一个已经存在的变量,但它仍然改变了值。
- 然后它用日志语句定义 drawChart,说明 PHP 年份是 2014(再次静态)。
- 当"callback"设置为
onLoadCallback
运行s(既运行after以上所有定义,向上到 #6,已完成),它使用 drawChart
的预期值(因为它是在 setOnLoadCallback
运行s 时计算的)。但是当那个函数是运行时,它使用year
. 的最新值
要解决此问题,您需要确保每个回调都有一个 永久 引用您想要 运行 的年份。
解决方案 1: 删除 "year" 变量并将值直接嵌入(来自 PHP)每个 "drawChart" 函数:
google.setOnLoadCallback(function() {
var id_chart = 'chart_'+<?=$anio->Año?>;
var year=<?=$anio->Año?>; console.log('First, the year value is '+year);
var data = <?= $difusion_stats->notas_stats_anio($anio->Año); ?>;
console.log('Inside the drawChart() function. Current year value is: '+year);
console.log('Php current year value is: '+<?=$anio->Año?>);
// ...
}
这使用 "anonymous function" 来确保 每个设置为回调的函数都是唯一的。
它还确保 JS var 声明在函数范围内,因此它们不会相互影响。
解决方案 2: 创建单个 drawChart 函数并使用参数调用它。
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
function getDrawChartFunction(year, data) {
return function() {
console.log('Inside the drawChart() function. Current year value is: '+year);
var data = google.visualization.arrayToDataTable(data);
var options = {
title: 'Distribución de notas y entrevistas en el año '+ year
//, ...
};
var chart = new google.visualization.PieChart(document.getElementById('chart_'+year));
chart.draw(data, options);
}; // End of return of *anonymous function closure*
}
<?php
foreach ($anios as $anio)
{
$datos=$difusion_stats->notas_stats_anio($anio->Año);
?>
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(getDrawChartFunction(
<?=$anio->Año?>,
<?=$datos?>
));
</script>
<?
}
?>
这个解决方案也使用了一个匿名函数,但是这次,它returns一个匿名闭包,每次使用不同的参数叫.
的帮助,请参阅我在程序员上的回答
记住:
无论哪种情况,您都需要确保调用 "google.setOnLoadCallback" 的 运行 代码是 运行 之后的 ("asynchronously",在图书馆 and/or 页的 "load" 之后 运行。
这意味着您在 运行 时更改了值。
要解决此类问题,您需要确保以某种方式绘制图表的函数 "remembers" 设置它们时需要的值。
您可以通过将值直接嵌入到一个独特的函数中,或创建一个指向正确值的 JavaScript 函数(闭包所做的)来实现这一点。
我有显示 google 图表的功能。我想显示存储在数据库中的每一年的图表。 几个小时以来我一直困扰的问题是,例如,变量
var year
始终将最后一年作为值。
例如,如果我想显示每年(2013 年和 2014 年)的图表,它只会显示 2014 年的图表,而忽略第一年。如果我只得到2013年的数据,它显示的是2013年的数据。
好像覆盖了所有数据,只保留最后一个值
我的代码如下:
<?php
foreach ($anios as $anio)
{
?>
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
<?php
$datos=$difusion_stats->notas_stats_anio($anio->Año);
?>
var year=<?=$anio->Año?>; console.log('First, the year value is '+year);
var data=<?=$datos?>;
var id_chart = 'chart_'+<?=$anio->Año?>;
function drawChart() {
console.log('Inside the drawChart() function. Current year value is: '+year);
console.log('Php current year value is: '+<?=$anio->Año?>);
var data = google.visualization.arrayToDataTable(<?=$datos?>);
var options = {
title: 'Distribución de notas y entrevistas en el año '+<?=$anio->Año?>,
legend: 'Porcentaje de los distintos tipos de eventos',
pieSliceText: 'texto',
slices : {
0 : {offset: 0.1}
},
/*sliceVisibilityThreshold: .2,//Para contraer el resto y poner "otro"*/
pieHole: 0.4,
backgroundColor: { fill:'transparent'},
tooltip: {showColorCode: true},
tooltip: {isHtml: true},
height: 400,
titleTextStyle: {
color: '#FFFFFF'
},
legendTextStyle: {
color: '#FFFFFF'
}
};
var chart = new google.visualization.PieChart(document.getElementById(id_chart));
chart.draw(data, options);
/*Para hacerlo responsive:
function resizeHandler () {
chart.draw(data, options);
}
if (window.addEventListener) {
window.addEventListener('resize', resizeHandler, false);
}
else if (window.attachEvent) {
window.attachEvent('onresize', resizeHandler);
}
}/*Fin de la función drawChart()*/
</script>
<?php
}/*Fin del foreach PHP*/
?>
在这种情况下,生成的 javascript 代码是每年的两个代码:2013 年和 2014 年:
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
var year=2013; console.log('First, the year value is '+year);
var data=[['tipo','Cantidad'],['nota',14],['entrevista',3]];
var id_chart = 'chart_'+2013;
function drawChart() {
console.log('Inside the drawChart() function. Current year value is: '+year);
console.log('Php current year value is: '+2013);
var data = google.visualization.arrayToDataTable([['tipo','Cantidad'],['nota',14],['entrevista',3]]);
var options = {
title: 'Distribución de notas y entrevistas en el año '+2013,
legend: 'Porcentaje de los distintos tipos de eventos',
pieSliceText: 'texto',
slices : {
0 : {offset: 0.1}
},
/*sliceVisibilityThreshold: .2,//Para contraer el resto y poner "otro"*/
pieHole: 0.4,
backgroundColor: { fill:'transparent'},
tooltip: {showColorCode: true},
tooltip: {isHtml: true},
height: 400,
titleTextStyle: {
color: '#FFFFFF'
},
legendTextStyle: {
color: '#FFFFFF'
}
};
var chart = new google.visualization.PieChart(document.getElementById(id_chart));
chart.draw(data, options);
/*Para hacerlo responsive:
function resizeHandler () {
chart.draw(data, options);
}
if (window.addEventListener) {
window.addEventListener('resize', resizeHandler, false);
}
else if (window.attachEvent) {
window.attachEvent('onresize', resizeHandler);
}
}/*Fin de la función drawChart()*/
</script>
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
var year=2014; console.log('First, the year value is '+year);
var data=[['tipo','Cantidad'],['nota',43],['entrevista',12]];
var id_chart = 'chart_'+2014;
function drawChart() {
console.log('Inside the drawChart() function. Current year value is: '+year);
console.log('Php current year value is: '+2014);
var data = google.visualization.arrayToDataTable([['tipo','Cantidad'],['nota',43],['entrevista',12]]);
var options = {
title: 'Distribución de notas y entrevistas en el año '+2014,
legend: 'Porcentaje de los distintos tipos de eventos',
pieSliceText: 'texto',
slices : {
0 : {offset: 0.1}
},
/*sliceVisibilityThreshold: .2,//Para contraer el resto y poner "otro"*/
pieHole: 0.4,
backgroundColor: { fill:'transparent'},
tooltip: {showColorCode: true},
tooltip: {isHtml: true},
height: 400,
titleTextStyle: {
color: '#FFFFFF'
},
legendTextStyle: {
color: '#FFFFFF'
}
};
var chart = new google.visualization.PieChart(document.getElementById(id_chart));
chart.draw(data, options);
/*Para hacerlo responsive:
function resizeHandler () {
chart.draw(data, options);
}
if (window.addEventListener) {
window.addEventListener('resize', resizeHandler, false);
}
else if (window.attachEvent) {
window.attachEvent('onresize', resizeHandler);
}
}/*Fin de la función drawChart()*/
</script>
但从未显示 2013 年的图表。 :/
在这种情况下,我得到两年:2013 年和 2014 年。但是,在控制台日志消息中,我看到它通过替换为去年来覆盖 2013 年,因此消息是:
First, the year value is 2013
stats:273 After calling the setOnLoadCallback() function, the year value is 2013
stats:274 we are about to call the drawChart() function ... YEAR: 2013
stats:280 First, the year value is 2014
stats:286 After calling the setOnLoadCallback() function, the year value is 2014
stats:287 we are about to call the drawChart() function ... YEAR: 2014
**stats:290 Inside the function. Current year value is: 2014**
stats:290 Inside the function. Current year value is: 2014
2013的值被2014覆盖了,为什么会这样? 我该如何解决这个问题?
在您的代码中,您已经定义了函数 draw_chart twice.Instead 您应该定义它一次,并在 2013 年和 2014 年使用不同的参数调用它两次。
您的第二个脚本标签包含 2014 年图表的代码,覆盖 2013 年,因此它只显示 2014 年
我不知道 PHP 但问题可能出在这一行 var id_chart = 'chart_'+<?=$anio->Año?>;
。所以试试 console.log(id_chart);
。如果每次都打印不同,那么它应该绘制两个不同的图表,具体取决于该元素是否存在于 DOM 中。否则
尝试改变
var chart = new google.visualization.PieChart(document.getElementById(id_chart));
到
var span=document.createElement('span');
document.getElementById(id_chart).appendChild(span);
var chart = new google.visualization.PieChart(span);
var year
在这两种情况下都被写入全局 JS 范围。当 drawChart
函数为 运行 时,两个 var year
命令都已为 运行,因此使用 2014 年。
它将帮助您将问题减少到更小的代码集,您将看到会发生什么:
<script type="text/javascript">
google.setOnLoadCallback(drawChart);
var year=2013; console.log('First, the year value is '+year);
function drawChart() {
console.log('Inside the drawChart() function. Current year value is: '+year);
console.log('Php current year value is: '+2013);
}
script>
<script type="text/javascript">
google.setOnLoadCallback(drawChart);
var year=2014; console.log('First, the year value is '+year);
function drawChart() {
console.log('Inside the drawChart() function. Current year value is: '+year);
console.log('Php current year value is: '+2014);
}/*Fin de la función drawChart()*/
</script>
- 它为一个名为
drawChart
的函数调用了setOnLoadCallback,这个函数还不存在(但是JavaScript中的声明是"hoisted",换句话说,后面的function drawChart
被认为存在于范围的顶部,因此它有效。) - 然后设置
year = 2013
. - 然后定义了drawChart的日志语句说PHP年是2013年(因为这段代码变成了静态JS代码)以及JS的current值是多少var
year
是. - 然后它再次为
drawChart
调用 setOnLoadCallback。 - 然后设置
year = 2014
。这在技术上是不正确的 JS,因为它使用var
作为一个已经存在的变量,但它仍然改变了值。 - 然后它用日志语句定义 drawChart,说明 PHP 年份是 2014(再次静态)。
- 当"callback"设置为
onLoadCallback
运行s(既运行after以上所有定义,向上到 #6,已完成),它使用drawChart
的预期值(因为它是在setOnLoadCallback
运行s 时计算的)。但是当那个函数是运行时,它使用year
. 的最新值
要解决此问题,您需要确保每个回调都有一个 永久 引用您想要 运行 的年份。
解决方案 1: 删除 "year" 变量并将值直接嵌入(来自 PHP)每个 "drawChart" 函数:
google.setOnLoadCallback(function() {
var id_chart = 'chart_'+<?=$anio->Año?>;
var year=<?=$anio->Año?>; console.log('First, the year value is '+year);
var data = <?= $difusion_stats->notas_stats_anio($anio->Año); ?>;
console.log('Inside the drawChart() function. Current year value is: '+year);
console.log('Php current year value is: '+<?=$anio->Año?>);
// ...
}
这使用 "anonymous function" 来确保 每个设置为回调的函数都是唯一的。
它还确保 JS var 声明在函数范围内,因此它们不会相互影响。
解决方案 2: 创建单个 drawChart 函数并使用参数调用它。
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
function getDrawChartFunction(year, data) {
return function() {
console.log('Inside the drawChart() function. Current year value is: '+year);
var data = google.visualization.arrayToDataTable(data);
var options = {
title: 'Distribución de notas y entrevistas en el año '+ year
//, ...
};
var chart = new google.visualization.PieChart(document.getElementById('chart_'+year));
chart.draw(data, options);
}; // End of return of *anonymous function closure*
}
<?php
foreach ($anios as $anio)
{
$datos=$difusion_stats->notas_stats_anio($anio->Año);
?>
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(getDrawChartFunction(
<?=$anio->Año?>,
<?=$datos?>
));
</script>
<?
}
?>
这个解决方案也使用了一个匿名函数,但是这次,它returns一个匿名闭包,每次使用不同的参数叫.
的帮助,请参阅我在程序员上的回答记住:
无论哪种情况,您都需要确保调用 "google.setOnLoadCallback" 的 运行 代码是 运行 之后的 ("asynchronously",在图书馆 and/or 页的 "load" 之后 运行。
这意味着您在 运行 时更改了值。
要解决此类问题,您需要确保以某种方式绘制图表的函数 "remembers" 设置它们时需要的值。
您可以通过将值直接嵌入到一个独特的函数中,或创建一个指向正确值的 JavaScript 函数(闭包所做的)来实现这一点。