# 实现 JavaScript 数组的逆序索引

需求： 实现一种新的数组特性

```javascript
// 实现一种新的数组特性，完成数组的逆序访问
const arr = [1,2,3]
arr[-1] = 3
arr[-2] = 2
arr[-3] = 1
```

思路

首先我们不谈这道题是什么解决的，单纯了解一下 数组如何存储的。

数组( Array )在内存中用一串连续的区域来存放一些值。注意「连续」一词，它至关重要。

![](/files/-MF9Q7EVChtrK1Nratf2)

上图表示存储在内存中的一个数组。存储4个4 bit 的元素,一共需要16 bit 存储区域，每个元素顺序保持一致。

假设，我声明了tinyInt arr\[4]，它占用从1201位置开始的一段存储区域。当某个时刻我尝试读取a\[2]，那么只要做简单的计算，找到a\[2]的位置就可以了。例如1201+(2X4)然后直接从1209位置读取数据。

However，JavaScript 的内存数据结构并不是连续的，而是链表结构。如果在 JavaScript 中声明var arr = new Array(4)；它会产生类似下图的结构。

![](/files/-MF9QC4xg5ncUWqyoMCY)

因此，如果你想在程序中某一处读取a\[2]，它必须从1201位置开始溯寻a\[2]的位置。

这就是 JavaScript 数组和真正的数组不同的地方

HowHowever,  以上只是简单科普一下 JavaScript Array 的数据结构。如果你准备构思如何改变 JavaScript 的链表结构来实现这道题。我只能祝你好运了。

真实的做法是利用 Proxy 或者 Object.defineProperty 来劫持 数组访问。直接上解决方案

```javascript
// proxy 写法
const NewArrProxy = {
  get (target, key, receiver) {
    let idx = key < 0 ? target.length + Number(key): key
    return Reflect.get(target, idx, receiver)
  }
}

const arr = new Proxy([1,2,3], NewArrProxy)
console.log(arr[-1])   // 3
console.log(arr[-2])   // 2
console.log(arr[-3])   // 1
```

```javascript
// object.definePropery 写法
const arr = [1,2,3]

function newArrObserver(arr){
  for (let idx = 1; idx <= arr.length; idx++) {
    Object.defineProperty(arr, `-${idx}`, {
      get() {
          return arr[arr.length - idx]
      }
    })
  }
}
newArrObserver(arr)

console.log(arr[-1])   // 3
console.log(arr[-2])   // 2
console.log(arr[-3])   // 1
```

惊不惊喜意不意外&#x20;

以上。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://mm.ricky.moe/blog/shi-xian-javascript-shu-zu-de-ni-xu-suo-yin.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
