在JavaScript中递归地通过继承构造序列/链表

时间:2015-07-09 01:34:25

标签: javascript recursion

背景:我正在阅读在线书籍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]));

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

2 个答案:

答案 0 :(得分:1)

正如我在评论中所说:

  • 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]));

答案 1 :(得分:0)

首先,splice是方法。

array.splice(1)代替array.splice[1]

并在数组=== []。

中使用array.length == 0

如果两个对象是不同的对象,则===运算符被视为false,即使所有元素都相同。