背景:我正在阅读在线书籍Eloquent JavaScript,第6章中的一项练习提到“序列”的行为类似于链接列表。 Here是练习的链接,我已经复制了一些相关的文本:


  另一种解决方案是避免更改对象的状态。您可以公开一种用于获取当前元素的方法(不增加任何计数器),以及一种用于获取一个新序列的方法,该序列表示当前元素之后的剩余元素(如果到达序列的末尾,则为特殊值)。


我正在尝试通过在接口类中递归调用实现类的(ArraySeq)构造函数来构建Sequence。但是,在节点中运行测试时,我得到了TypeError: Cannot read property '0' of undefined at Sequence.ArraySeq

我已经复制并粘贴了(不完整的)实现:

/**
 * Sequence interface
 */
function Sequence(current, rest) {
  this.current = current;
  this.rest = rest;
}

Object.defineProperty(Sequence.prototype, "end", {
  get: function() {
    return this.rest === undefined;
  }
});

Sequence.prototype.next = function() {
  return this.rest;
};

/**
 * Array implementation of sequence
 */
function ArraySeq(array) {
  if (array === []) {
    Sequence.call(undefined, undefined);
  } else {
    Sequence.call(array[0], new ArraySeq(array.slice(1)));
  }
}

ArraySeq.prototype = Object.create(Sequence.prototype);

/**
 * Logs all elements in a Sequence
 */
function logSequence(sequence) {
  while (sequence.rest !== undefined) {
    console.log(sequence.current);
    sequence = sequence.rest;
  }
}

logSequence(new ArraySeq([1, 2]));


感谢您阅读本文,非常感谢您的帮助或指导!

最佳答案

正如我在评论中指出的:


array.splice[1]将为您提供不确定的信息。您需要array.slice(1)-没有第一个元素的整个数组:slice,而不是splicearray.splice(1)将从数组中删除第二个元素,然后返回该元素-不是您想要的。
您将Sequence写为构造函数,但没有将其称为构造函数。代替Sequence.call,使用new Sequence
相反,您正在调用new ArraySeq,但是ArraySeq看起来不像构造函数。仅使用ArraySeq,并使其返回内容(return new Sequence...)。
使用if (!array.length)测试数组是否为非空。 array === []甚至array == []都永远不会返回true,因为对象(以及数组)是根据对象标识而不是相等性进行比较的,而您只是创建了一个新对象(因此,不可能有同一个对象作为已经存在的东西)。
当然,没有定义ArraySequence。应该是ArraySeq,对吧?


有了这些更改,您的代码就可以工作。编辑:但是,练习希望ArraySeq是一个对象,因此仍然需要更多工作...首先,“接口”不是对象。这就是对象的行为方式。我的练习是:

function ArraySeq(array) {
  this.array = array;
  this.index = 0;
}

Object.defineProperty(ArraySeq.prototype, "end", {
  get: function() {
    return this.index >= this.array.length;
  }
});

Object.defineProperty(ArraySeq.prototype, "next", {
  get: function() {
    return this.array[this.index++];
  }
});


/**
 * Logs all elements in a Sequence
 */
function logSequence(sequence) {
  while (!sequence.end) {
    console.log(sequence.next);
  }
}

logSequence(new ArraySeq([1, 2]));


这里的“接口”是.end.next。如果您想走报价的路线,则略有变化。这里的接口是.end.rest.value

function ArraySeq(array) {
  this.array = array;
}

Object.defineProperty(ArraySeq.prototype, "end", {
  get: function() {
    return this.array.length == 0;
  }
});

Object.defineProperty(ArraySeq.prototype, "rest", {
  get: function() {
    return new ArraySeq(this.array.slice(1));
  }
});

Object.defineProperty(ArraySeq.prototype, "value", {
  get: function() {
    return this.array[0];
  }
});


/**
 * Logs all elements in a Sequence
 */
function logSequence(sequence) {
  while (!sequence.end) {
    console.log(sequence.value);
    sequence = sequence.rest;
  }
}

logSequence(new ArraySeq([1, 2]));

关于javascript - 在JavaScript中通过继承递归构造序列/链接列表,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31306674/

10-12 15:42