krahets/hello-algo · error · Error

索引越界

Error message

索引越界

What it means

Thrown by the get(index) accessor of a hand-written dynamic-list (MyList) class when the requested index falls outside the populated range [0, size). This is a bounds guard on the backing array #arr; #capacity is the allocated length but only #size slots hold valid elements, so valid access stops at size-1. The check mirrors how Array.prototype / ArrayList style containers reject reads past their logical length.

Source

Thrown at codes/javascript/chapter_array_and_linkedlist/my_list.js:32

    /* 构造方法 */
    constructor() {
        this.#arr = new Array(this.#capacity);
    }

    /* 获取列表长度(当前元素数量)*/
    size() {
        return this.#size;
    }

    /* 获取列表容量 */
    capacity() {
        return this.#capacity;
    }

    /* 访问元素 */
    get(index) {
        // 索引如果越界,则抛出异常,下同
        if (index < 0 || index >= this.#size) throw new Error('索引越界');
        return this.#arr[index];
    }

    /* 更新元素 */
    set(index, num) {
        if (index < 0 || index >= this.#size) throw new Error('索引越界');
        this.#arr[index] = num;
    }

    /* 在尾部添加元素 */
    add(num) {
        // 如果长度等于容量,则需要扩容
        if (this.#size === this.#capacity) {
            this.extendCapacity();
        }
        // 将新元素添加到列表尾部
        this.#arr[this.#size] = num;
        this.#size++;

View on GitHub (pinned to 69932aed18)

Solutions

  1. Read list.size() first and constrain the index with i >= 0 && i < list.size() before calling get(i).
  2. Fix the loop bound from i<=size to i<size.
  3. Recompute the bound after any add/remove/insert that changes size; do not cache size across mutations.
  4. Use the native Array or the list's toArray() when you only need sequential read access.

Example fix

// before
for (let i = 0; i <= list.size(); i++) {
  console.log(list.get(i)); // throws at i === size
}
// after
for (let i = 0; i < list.size(); i++) {
  console.log(list.get(i));
}
Defensive patterns

Strategy: validation

Validate before calling

function safeGet(list, i) {
  if (i >= 0 && i < list.size()) return list.get(i);
  throw new RangeError(`index ${i} out of [0, ${list.size()})`);
}

Type guard

function isValidIndex(list, i): i is number {
  return typeof i === 'number' && Number.isInteger(i) && i >= 0 && i < list.size();
}

Try / catch

try {
  const v = list.get(i);
} catch (e) {
  if (e instanceof Error && e.message === '索引越界') {
    // handle invalid index, e.g. return default or skip
  } else throw e;
}

Prevention

When it happens

Trigger: Calling list.get(-1), list.get(n) where n equals the current size (e.g. after pushing exactly n items), or calling get() on a freshly constructed list (size 0) with index 0. Any index >= list.size() or < 0 triggers it.

Common situations: Off-by-one loops (for (let i=0; i<=size; i++) then get(i)); reading an index that was valid before a remove() shrunk the list; assuming capacity() == size() and indexing up to capacity; iterating a list that was cleared without resetting the loop bound.

Related errors


AI-assisted analysis of krahets/hello-algo@69932aed18 (2026-08-13). Data as JSON: /api/errors/54a10a9a7a0dfbf4. Report an issue: GitHub.