javascript - 全局变量、函数和 Javascript

标签 javascript google-visualization

对我认为是这样一个基本问题表示歉意,但是对 javascript 函数进行粗略的谷歌搜索会返回有关“this”的各种内容,以及为什么不全局声明事物并创建对象——所有这些都已经结束了我的头。

我正在尝试使用 制作交互式地理图表。我这里有一个工作版本(有点):

<!--
You are free to copy and use this sample in accordance with the terms of the
Apache license (http://www.apache.org/licenses/LICENSE-2.0.html)
-->

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  <title>Google Visualization API Sample</title>
  <script type="text/javascript" src="http://www.google.com/jsapi"></script>
  <script type="text/javascript">
    google.load('visualization', '1', {packages: ['geochart']});

    var width, height, selectedRegion, resolution;

    window.onload = function(){
      width = 556;
      height = 400;
      selectedRegion = 'world';
      resolution = 'subcontinents';
    };

    function drawVisualization() {
      var data = new google.visualization.DataTable();
      data.addColumn('string', 'Region');
      data.addColumn('number', 'Value');
      data.addRows([
        [{v:"005", f:"South America"}, 978.7],
        [{v:"011", f:"Western Africa"}, 46],
        [{v:"013", f:"Central America"}, 299],
        [{v:"014", f:"Eastern Africa"}, 63.9],
        [{v:"015", f:"Northern Africa"}, 255.7],
        [{v:"017", f:"Middle Africa"}, 21.4],
        [{v:"018", f:"Southern Africa"}, 244.5],
        [{v:"029", f:"Caribbean"}, 76.5],
        [{v:"030", f:"Eastern Asia"}, 5712.9],
        [{v:"034", f:"Southern Asia"}, 1275.1],
        [{v:"035", f:"South-Eastern Asia"}, 639.2],
        [{v:"039", f:"Southern Europe"}, 777.8],
        [{v:"053", f:"Australia and New Zealand"}, 272],
        [{v:"054", f:"Melanesia"}, 6.3],
        [{v:"057", f:"Micronesia"}, 1.8],
        [{v:"061", f:"Polynesia"}, 1],
        [{v:"143", f:"Central Asia"}, 170.3],
        [{v:"145", f:"Western Asia"}, 834.1],
        [{v:"151", f:"Eastern Europe"}, 1587.6],
        [{v:"154", f:"Northern Europe"}, 801.5],
        [{v:"155", f:"Western Europe"}, 1456.2],
        [{v:"021", f:"Northern America"}, 4704.1]
      ]);

      var options = {
        displayMode: 'regions',
        enableRegionInteractivity: 'true',
        resolution: resolution,
        region: selectedRegion,
        height: height,
        width: width
      };

      var geochart = new google.visualization.GeoChart(
          document.getElementById('visualization'));

      google.visualization.events.addListener(geochart, 'select', function() {
        var selection = geochart.getSelection();

        if (selection.length == 1) {
          var selectedRow = selection[0].row;
          selectedRegion = data.getValue(selectedRow, 0);
          resolution = "countries";
          options.region = selectedRegion;
          options.resolution = resolution;
          //alert(resolution);
          geochart.draw(data, options);
          }
      });

      geochart.draw(data, options);
    }

    google.setOnLoadCallback(drawVisualization);
  </script>
</head>
<body style="font-family: Arial;border: 0 none;">
<div id="visualization"></div>
</body>
</html>

代码正确执行的操作(以及我想要作为更大项目的一部分进行改进的操作)是,当您单击 map 上的某个区域时,它将更改 map 的选项并重新绘制它,以进一步放大该地区。

这太棒了,但上面是一个庞大的函数,函数内部有一个处理函数。这会变得非常笨拙,因为我必须添加诸如缩小和重置 map 以查看整个世界之类的内容,并且还必须根据选择的区域调整更大的数据集(上面的示例将放大一个区域,然后当前不显示任何数据)。

因此,我想将我的代码分成更易于管理的 block ,这些 block 可以单独调试,让我更好地了解哪里出了问题,并且通常使整个项目更易于管理,因为我距离专家程序员(说实话,可能与新手程序员相差甚远)。

以下是我想要将其分解为的 block :

  1. 定义数据(每次更改选项时)
  2. 定义选项(每次更改选项时)
  3. 绘制 map (每次执行函数5-7时)
  4. 添加监听器(一次)
  5. 放大 map 的功能(点击)
  6. 缩小 map 的功能(点击时)
  7. 重置 map 的功能(点击时)
  8. 操作数据的函数(每次执行函数 5-7 时)

我遇到的问题是在非常基本的事情上。我可以在全局范围内声明所有变量(无需在它们前面加上 var 前缀),但我认为这通常是不鼓励的,并且从长远来看可能会伤害我(特别是如果我有一个巨大的数据表,其中声明了 10,000 个元素)。 如果这是错误的,请纠正我——从我有限的理解来看,使用全局变量是一件坏事,但也许 javascript 很特别?

让我们关注其中一个函数,然后如果我了解该函数如何工作和交互,那么我可能就能弄清楚其他函数。

要绘制图表,我需要两条信息:

  1. 使用哪些数据
  2. 使用哪些选项

现在,如果我将数据和选项都声明为全局变量,我可以愉快地从其他函数中操作它们(非常感谢),但它们是全局的。我不知道如何将这些内容传递给函数,并根据需要返回调整后的数据。

例如,我可以轻松创建工作 map ,如下所示:

function drawVisualization() {
  var rawData = new google.visualization.DataTable();
  rawData.addColumn('string','Continent');
  rawData.addColumn('string','Subontinent');
  rawData.addColumn('string','Country');
  rawData.addColumn('number','Data');
  rawData.addRows([
    [{v:"142",f:"Asia"},{v:"145",f:"Western Asia"},{v:"AE",f:"United Arab Emirates"},91.9],
    // more data in between
    [{v:"002",f:"Africa"},{v:"014",f:"Eastern Africa"},{v:"ZW",f:"Zimbabwe"},7.8],
  ]);

  resetMap();

  var data = new google.visualization.DataView(rawData);
  data.setColumns([resolutionIndex, 3]);

  var options = {
    displayMode: displayMode,
    enableRegionInteractivity: 'true',
    resolution: resolution,
    region: region,
    height: height,
    width: width
  };

  drawMap(data, options);

}

function drawMap(data, options) {
  var geochart = new google.visualization.GeoChart(document.getElementById('visualization'));
  geochart.draw(data, options);
}

function resetMap() {
  resolutionArray = ['continents', 'subcontinents', 'countries'];
  resolutionIndex = 0;
  previousIndex = 0;
  previousRegion = 'world';
  displayMode = 'regions';
  resolution = resolutionArray[resolutionIndex];
  region = 'world';
  height = '600';
  width = '800';
}

现在这段代码的问题是我必须将“options”变量内的所有这些变量设置为全局变量,并且我不太确定更新 resolution 函数内的 resetMap() 等变量实际上会影响内部的值选项(我需要创建另一个函数来更新 options 变量吗?)。而且一切似乎都是全局的,我不确定如何来回传递变量并确保它们一起工作来完成工作。

我知道这是一篇非常长的文章,可能有一个非常简单的概念可以为我解决这个问题,但我就是无法理解它。如果有人有任何一般性的指示,或者为真正的初学者编写的关于函数如何在 javascript 中工作的描述(函数如何工作、如何定义它们、如何从它们返回值等),我将非常感激。

最佳答案

您担心拥有全局变量(这很好!)而不知道确切原因(这很糟糕!)。它们的主要问题是,现在在网页中组合来自不同来源的脚本是很常见的。如果它们都使用全局变量,则由于命名冲突而干扰(并破坏)另一个变量的可能性很高。因此,最佳实践是避免全局变量。

为此,您必须了解的第一件事是 how scope works in JavaScript 。每个函数都会创建一个新的作用域,因此在函数内部声明的 var 仅在该作用域中可见。它在嵌套函数中也是可见的(通过 closure )。如果您想避免全局变量,那么理解这两个概念至关重要。

还有一个简单的语言功能可以帮助您:“立即调用函数表达式”(IIFE)可用于将代码块包装在其自己的范围内。可以使用该作用域代替全局作用域来与内部函数共享变量,内部函数可以通过闭包访问它们:

(function(){
    // declare common variables here
    var a = 1, b = 2, c = 3;

    // any function declare here can access a, b, c
    function foo() {
        console.log(a);
    }

    // works with anynymous function expressions too
    document.addEventListener('click', function(e) {
        alert(b);
    });
}());

这允许您拥有与已有代码非常相似的代码,但不会泄漏任何全局变量。

使用object-oriented js还可以帮助您构建代码,但这是一个广泛的主题,除非您询问更具体的问题,否则我无法在这里讨论任何细节。

关于javascript - 全局变量、函数和 Javascript,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14950389/

相关文章:

javascript - javascript中的多维json解析

javascript - 如何告诉 postMessage 结构化克隆忽略属性?

java - 无法使用 REST 服务绘制 Google 图表

javascript - 即使我定义了自己的函数,Google 可视化表也会排序

svg - 使用 Google 图表工具的范围标记

javascript - 加密稍后解密的数据

javascript - 当所有 3 个输入都有值时如何启用搜索按钮?

angularjs - 等待 Angular2 中定义元素

javascript - 为什么我使用 jest-dom 时会报错 "TypeError: expect(...).not.toBeVisible is not a function"

javascript - 当使用 css 属性提供一些边距空间时,图像未显示在给定位置