提高javascript函数的可读性和质量

时间:2015-12-11 10:46:18

标签: javascript jquery html

我有一个函数,它使用所有预合并表共有的值将许多HTML表合并到一个结果表中。

enter image description here

我现在正在寻求提高javascript函数的速度和可靠性。函数gatherData()遍历每个预合并表,并将数据分别放入每个表的对象结构中。函数results()循环遍历这些对象,并使用公共值填充结果表,在此示例中为日期。

这段代码写得很快,我知道它非常难看。

$(document).ready(function(){
    gatherData();
    results();
});

function gatherData(){
    data = [];

    tables = $('.before').find('table');

    $(tables).each(function(index){
        table = [];

        var headers = $(this).find('tr:first');
        var headerText = [];
        headerText.push($(headers).find('td:nth-child(1)').text());     
        headerText.push($(headers).find('td:nth-child(2)').text());
        table.push(headerText)
        $(this).find('tr').each(function(index){
            var rowContent = [];
            if (index != 0){
                $(this).find('td').each(function(index){
                    rowContent.push($(this).text());
                })
            }
            table.push(rowContent)
        })
        data.push({table: table})
    });
}

function results(){
    var results = $('.after1').find('thead');

    $(results).append("<th>" + data[0].table[0][0] + "</th>");

    for (i in data){
        console.log(i)
        $(results).append("<th>" + data[i].table[0][1] + "</th>");
    }

    var b = data[i].table.length;
    var rowString = "";
    for (a = 2; a < b; a++){
        rowString = rowString + "<tr>";
        rowString = rowString + "<td>" + data[i].table[a][0] + "</td>"
        for (i in data){
            rowString = rowString + "<td>" + data[i].table[a][1] + "</td>"
        }
        rowString = rowString + "</tr>"
    }
    $('.after1').append(rowString)
}

对象的结构如下:

enter image description here

有关信息

每个表的实际数据从data[i].table[2]开始,其中日期为data[i].table[2][0],该日期的值为data[i].table[2][1]。这就是for for循环a中的for (a = 2; a < data[i].table.length; a++) var从2开始的原因。

Here是指向我的CodePen的链接。

1 个答案:

答案 0 :(得分:1)

实际上,您的代码并没有按照预期的方式工作,而且它在某种程度上非常硬编码(连接键始终是第一列,它只考虑了前两列)。 This pen显示了如何无法提供人们期望的正确结果。

&#13;
&#13;
$(document).ready(function() {
  gatherData();
  results();
});

function gatherData() {
  data = [];

  tables = $('.before').find('table');

  $(tables).each(function(index) {
    table = [];

    var headers = $(this).find('tr:first');
    var headerText = [];
    headerText.push($(headers).find('td:nth-child(1)').text());
    headerText.push($(headers).find('td:nth-child(2)').text());
    table.push(headerText)
    $(this).find('tr').each(function(index) {
      var rowContent = [];
      if (index != 0) {
        $(this).find('td').each(function(index) {
          rowContent.push($(this).text());
        })
      }
      table.push(rowContent)
    })
    data.push({
      table: table
    })
  });
}

function results() {
  var results = $('.after1').find('thead');

  $(results).append("<th>" + data[0].table[0][0] + "</th>");

  for (i in data) {
    console.log(i)
    $(results).append("<th>" + data[i].table[0][1] + "</th>");
  }

  var b = data[i].table.length;
  var rowString = "";
  for (a = 2; a < b; a++) {
    rowString = rowString + "<tr>";
    rowString = rowString + "<td>" + data[i].table[a][0] + "</td>"
    for (i in data) {
      rowString = rowString + "<td>" + data[i].table[a][1] + "</td>"
    }
    rowString = rowString + "</tr>"
  }
  $('.after1').append(rowString)
}
&#13;
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
  <meta name="description" content="">
  <meta name="author" content="">

  <title>Formatter.js</title>

  <!-- Bootstrap core CSS -->
  <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
</head>

<body>


  <div class="container">
    <h1 class="page-header">Formatter.js <small>DPD reports</small></h1>
  </div>
  <div class="container before">
    <h3>Before</h3>
    <TABLE border=1 cellspacing=0 cellpadding=0 alignment="">
      <TBODY>
        <TR>
          <TD>x-value</TD>
          <TD>La</TD>
        </TR>
        <TR>
          <TD>1</TD>
          <TD>a</TD>
        </TR>
        <TR>
          <TD>2</TD>
          <TD>b</TD>
        </TR>
      </TBODY>
    </TABLE>
    <TABLE border=1 cellspacing=0 cellpadding=0 alignment="">
      <TBODY>
        <TR>
          <TD>x-value</TD>
          <TD>Lx</TD>
          <TD>Lxx</TD>
        </TR>
        <TR>
          <TD>1</TD>
          <TD>x</TD>
          <TD>xx</TD>
        </TR>
        <TR>
          <TD>3</TD>
          <TD>y</TD>
          <TD>yy</TD>
        </TR>
      </TBODY>
    </TABLE>
    <TABLE border=1 cellspacing=0 cellpadding=0 alignment="">
      <TBODY>
        <TR>
          <TD>Random</TD>
          <TD>Lz</TD>
          <TD>Lzz</TD>
        </TR>
        <TR>
          <TD>1</TD>
          <TD>z</TD>
          <TD>zz</TD>
        </TR>
        <TR>
          <TD>2</TD>
          <TD>t</TD>
          <TD>tt</TD>
        </TR>
      </TBODY>
    </TABLE>
    <hr>
  </div>
  <div class="container after">
    <h3>After</h3>
    <table class="table after1">
      <thead>
      </thead>
      <tbody>
      </tbody>
    </table>
  </div>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js"></script>
  <script src="formatter4.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
</body>

</html>
&#13;
&#13;
&#13;

总结一下,对于表格:

x-value | La    x-value | Lx | Lxx    Random | Lz | Lzz
--------+----   --------+----+-----   -------+----+-----
1       | a     1       | x  | xx     1      | z  | zz
2       | b     3       | y  | yy     2      | t  | tt

大多数人会期望以下结果(有或没有第2行和/或第3行,具体取决于您实际想要对数据做什么):

x-value | La | Lx | Lxx 
--------+----+----+-----
1       | a  | x  | xx  
2       | b  |    |     
3       |    | y  | yy  

您的代码混合了表(只是连接它们,而不考虑实际的列标题(如果它是x-value或不是),而不考虑表连接的实际值(只是表中行的位置,因此row 1将与row 2连接,无论如何),它忽略除前两列之外的所有列,产生以下结果:

x-value | La | Lx | Lz 
--------+----+----+----
1       | a  | x  | z  
2       | b  | y  | t  

当我想亲自动手时,this pen包含更完整的解决方案。

&#13;
&#13;
$(document).ready(function(){
	createResultsTable($('.after1'), gatherData($('.before').find('table'), 'x-value'), sortDatesDescending);
});

function sortDatesDescending(keys) {
  function getDate(dateStr) {
    var date = dateStr.match(/^(\d{2})\/(\d{2})\/(\d{4})$/);
    return new Date(date[3], date[2], date[1]);
  }
  return keys.sort(function (key1, key2) { key1 = getDate(key1); key2 = getDate(key2); return key1 < key2 ? 1 : key1 == key2 ? 0 : -1; });
}

function gatherData(tables, joinColumn){
	var data = {};
  var dataHeaders = [];

	tables.each(function(index) {
    var table = $(this);
		var headerText = [];
    
    var joinColumnIndex = -1;
    table.find('tr:first').find('td').each(function(index, header) {
      header = header.innerText;
      if (header === joinColumn) joinColumnIndex = index;
      headerText.push(header);
    });
    if (joinColumnIndex < 0) return;
    
		table.find('tr').each(function(index){
      if (index === 0) return;
			var rowContent = [];
      $(this).find('td').each(function(index){
        rowContent.push(this.innerText);
      });
		  data[rowContent[joinColumnIndex]] = data[rowContent[joinColumnIndex]] || [];
      data[rowContent[joinColumnIndex]].push(rowContent);
		})
    dataHeaders.push(headerText);
	});
  console.log(data, dataHeaders);// here goes
  return {data: data, headers: dataHeaders, joinColumn: joinColumn};
}

function createResultsTable(resultsTable, data, orderFunction) {
  var resultsHead = '<thead><th>'+data.joinColumn+'</th>';
  var resultsBody = '<tbody>';
  data.headers.forEach(function (headers) {
    headers.forEach(function (header) {
      if (header !== data.joinColumn) resultsHead += '<th>'+header+'</th>';
    });
  });
  resultsHead += '</thead>';
  (orderFunction ? orderFunction(Object.keys(data.data)) : Object.keys(data.data))
    .forEach(function (joinValue) {
    resultsBody += '<tr><td>'+joinValue+'</td>';
    data.data[joinValue].forEach(function (subData, tableIndex) {
      data.headers[tableIndex].forEach(function (header, index) {
        if (header === data.joinColumn) return;
        resultsBody += '<td>'+subData[index]+'</td>';
      })
    });
    resultsBody += '</tr>';
  });
  resultsBody += '</tbody>';
  resultsTable.html(resultsHead+resultsBody);
}
&#13;
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
  <meta name="description" content="">
  <meta name="author" content="">

  <title>Formatter.js</title>

  <!-- Bootstrap core CSS -->
  <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
</head>

<body>


  <div class="container">
    <h1 class="page-header">Formatter.js <small>DPD reports</small></h1>
  </div>
  <div class="container before">
    <h3>Before</h3>
    <TABLE border=1 cellspacing=0 cellpadding=0 alignment="">
      <TBODY>
        <TR>
          <TD>x-value</TD>
          <TD>Operational Planned</TD>
          <td>Extra data</td>
        </TR>
        <TR>
          <TD>09/11/2015</TD>
          <TD>0</TD>
          <TD>extra1</TD>
        </TR>
        <TR>
          <TD>10/11/2015</TD>
          <TD>0</TD>
          <TD>extra2</TD>
        </TR>
        <TR>
          <TD>11/11/2015</TD>
          <TD>66358</TD>
          <TD>extra3</TD>
        </TR>
        <TR>
          <TD>12/11/2015</TD>
          <TD>65990</TD>
          <TD>extra4</TD>
        </TR>
        <TR>
          <TD>13/11/2015</TD>
          <TD>55993</TD>
          <TD>extra5</TD>
        </TR>
        <TR>
          <TD>14/11/2015</TD>
          <TD>0</TD>
          <TD>extra6</TD>
        </TR>
        <TR>
          <TD>15/11/2015</TD>
          <TD>0</TD>
          <TD>extra7</TD>
        </TR>
      </TBODY>
    </TABLE>
    <TABLE border=1 cellspacing=0 cellpadding=0 alignment="">
      <TBODY>
        <TR>
          <TD>x-value</TD>
          <TD>Actual</TD>
        </TR>
        <TR>
          <TD>09/11/2015</TD>
          <TD>0</TD>
        </TR>
        <TR>
          <TD>10/11/2015</TD>
          <TD>0</TD>
        </TR>
        <TR>
          <TD>11/11/2015</TD>
          <TD>62202</TD>
        </TR>
        <TR>
          <TD>12/11/2015</TD>
          <TD>59261</TD>
        </TR>
        <TR>
          <TD>13/11/2015</TD>
          <TD>49119</TD>
        </TR>
        <TR>
          <TD>14/11/2015</TD>
          <TD>0</TD>
        </TR>
        <TR>
          <TD>15/11/2015</TD>
          <TD>0</TD>
        </TR>
      </TBODY>
    </TABLE>
    <TABLE border=1 cellspacing=0 cellpadding=0 alignment="">
      <TBODY>
        <TR>
          <TD>not the x-value</TD>
          <TD>something</TD>
        </TR>
        <TR>
          <TD>09/11/2015</TD>
          <TD>0</TD>
        </TR>
        <TR>
          <TD>10/11/2015</TD>
          <TD>0</TD>
        </TR>
        <TR>
          <TD>11/11/2015</TD>
          <TD>62202</TD>
        </TR>
        <TR>
          <TD>12/11/2015</TD>
          <TD>59261</TD>
        </TR>
        <TR>
          <TD>13/11/2015</TD>
          <TD>49119</TD>
        </TR>
        <TR>
          <TD>14/11/2015</TD>
          <TD>0</TD>
        </TR>
        <TR>
          <TD>15/11/2015</TD>
          <TD>0</TD>
        </TR>
      </TBODY>
    </TABLE>
    <TABLE border=1 cellspacing=0 cellpadding=0 alignment="">
      <TBODY>
        <TR>
          <TD>x-value</TD>
          <TD>Financial Plan</TD>
        </TR>
        <TR>
          <TD>09/11/2015</TD>
          <TD>0</TD>
        </TR>
        <TR>
          <TD>10/11/2015</TD>
          <TD>0</TD>
        </TR>
        <TR>
          <TD>11/11/2015</TD>
          <TD>0</TD>
        </TR>
        <TR>
          <TD>12/11/2015</TD>
          <TD>890</TD>
        </TR>
        <TR>
          <TD>13/11/2015</TD>
          <TD>0</TD>
        </TR>
        <TR>
          <TD>14/11/2015</TD>
          <TD>3562</TD>
        </TR>
        <TR>
          <TD>15/11/2015</TD>
          <TD>7821</TD>
        </TR>
      </TBODY>
    </TABLE>
    <table border=1 cellspacing=0 cellpadding=0 alignment="">
      <tr>
        <td>Additional info</td><td>x-value</td>
      </tr>
      <tr>
        <td>marked</td><td>11/11/2015</td>
      </tr>
      <tr>
        <td>important</td><td>09/11/2015</td>
      </tr>
    </table>      
    <hr>
  </div>
  <div class="container after">
    <h3>After</h3>
    <table class="table after1">
      <thead>
      </thead>
      <tbody>
      </tbody>
    </table>
  </div>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js"></script>
  <script src="formatter4.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
</body>

</html>
&#13;
&#13;
&#13;

此代码:

  • 允许连接任意列数的表
  • 将列上的数据与函数参数
  • 中指定的列名匹配
  • 允许连接列位于表格中的任何位置(可以是第一个,第二个或任何实际正确命名的列)
  • 忽略没有指定连接列的表格
  • 更通用,允许您传入一个数组,其中哪些表是输入,哪个表是输出
  • 另外,它允许您在结果数组的键上定义排序/过滤功能(小心,您不能更改它们的实际值,只需对它们进行排序和过滤)。如果您不想要这个功能,请暂停参数

希望它有所帮助,这是一个有趣的项目。 :)