调用 javascript 成员函数未按预期列出 return

Calling javascript member function does not return list as expected

我正在使用此代码:

class CsvParser {
  constructor(csv, field_separator = ",") {
    this.field_separator = field_separator;
    this.csv = csv;
        this.index = 0;
        this.first = true;
  }

  get_next_record(record) {
        record = this.csv.split(',');
        if(this.first) {
          this.first = false;
        } else {
          return false;
        }
        return true;
  }
}

function process_csv(contents) {

     const parser = new CsvParser(contents);
     let record = [];
     while(parser.get_next_record(record)) {
        console.log(record);
     }
     
    console.log("exiting process_csv");
}

process_csv("1,2,3");

运行 通过此网页:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>CsvParser demo</title>
    <script src="csvparser.js"></script>
  </head>
  <body>
  </body>
</html>

如果我运行这个javascript,控制台输出是:

[]
exiting process_csv

为什么调用get_next_record成员函数后记录没有填充记录?

这段代码当然不完整。我的想法是 get_next_record 将被重复调用,直到到达内容的末尾,在这种情况下 get_next_record 函数将 return false。

我想如果我尝试简单地 return 记录那么如何表示我们已经到达内容的末尾?

这大概不是 javascript 中的处理方式。在 javascript 中设计 class/function 的惯用方法是什么?不支持引用调用吗?

您只在 get_next_record 中返回布尔值。您甚至没有跟踪索引。您也没有从 class 中的任何地方返回记录。您也没有按换行符拆分(但我不确定您是否尝试这样做)。这将在一行上工作:

class CsvParser {
  constructor(csv, field_separator = ",") {
    this.field_separator = field_separator;
    this.csv = csv;
        this.index = 0;
        this.first = true;
  }

  get_next_record(record) {
        record = this.csv.split(this.field_seperator);
        if(this.first) {
          this.first = false;
        } 
        this.index++;
        return record[this.index-1];
  }
}

function process_csv(contents) {

     const parser = new CsvParser(contents);
     let record;
     while(record = parser.get_next_record(record)) {
        console.log(record);
     }
     
    console.log("exiting process_csv");
}

例如:

process_csv("1,2,3");
1
2
3
exiting process_csv

我相信迭代器更适合这种类型的控制流。您可以通过编写一个生成器函数和一个 for...of 循环来隐式使用迭代器来使用它:

function* records(csv, separator = ',') {
  let currIndex = 0;

  while (currIndex !== -1) {
    const nextIndex = csv.indexOf(separator, currIndex);

    if (nextIndex === -1) {
      yield csv.slice(currIndex);
      currIndex = nextIndex;
    } else {
      yield csv.slice(currIndex, nextIndex);
      currIndex = nextIndex + 1;
    }
  }
}

for (const record of records('1,2,3')) {
  console.log(record);
}

或者您可以显式使用迭代器:

function records(csv, separator = ',') {
  let currIndex = 0;

  return {
    [Symbol.iterator]() {
      return this;
    },
    next() {
      if (currIndex === -1) {
        return { done: true };      
      }

      const nextIndex = csv.indexOf(separator, currIndex);

      if (nextIndex === -1) {
        const value = csv.slice(currIndex);
        currIndex = nextIndex;
        return { done: false, value };
      } else {
        const value = csv.slice(currIndex, nextIndex);
        currIndex = nextIndex + 1;
        return { done: false, value };
      }
    }
  };
}

const iter = records('1,2,3');
let result;

while (!(result = iter.next()).done) {
  console.log(result.value);
}

请注意,iterator implements the next() method, an iterable implements the [Symbol.iterator] method, and a generator object implements both. for...of 将适用于任何生成器对象,即使它是手动实现的:

function records(csv, separator = ',') {
  let currIndex = 0;

  return {
    [Symbol.iterator]() {
      return this;
    },
    next() {
      if (currIndex === -1) {
        return { done: true };      
      }

      const nextIndex = csv.indexOf(separator, currIndex);

      if (nextIndex === -1) {
        const value = csv.slice(currIndex);
        currIndex = nextIndex;
        return { done: false, value };
      } else {
        const value = csv.slice(currIndex, nextIndex);
        currIndex = nextIndex + 1;
        return { done: false, value };
      }
    }
  };
}

for (const record of records('1,2,3')) {
  console.log(record);
}