1

我有一个数组:

const arr = ['a', 'b', 'c']

我使用处理程序为该数组创建了一个代理,该处理程序将为每个 numberget返回带有索引的属性。例如,将返回、–和– 。n - 1np[1]'a'p[2]'b'p[3]'c'

const p = new Proxy(arr, {
  get: (target, property, receiver) => {
    const parsed = parseInt(property, 10)
    if (!Number.isNaN(parsed)) return target[parsed - 1]
    return target[property]
  }
})

它似乎工作正常。p[2],例如,给出'b'应该的。但是,还有另一个问题。Array.prototype.indexOf()不再正常工作。当我通过'a'或时它确实有效'b'- 它分别返回1and 2,但'c'它返回-1。事实证明,这indexOf()也触发了get处理程序。通过添加console.log(property)get处理程序,我们得到以下输出p.indexOf('c')

'indexOf'
'length'
'0'
'1'
'2'

似乎indexOf()内部检查了length属性,然后将数组从 index 迭代0length - 1.

如果我知道该属性是直接访问(如p[2])还是内部访问,那么解决这个问题将是微不足道的。然后我总是可以返回target[property]内部访问(所以代理将是无操作的)。

如何区分代理get处理程序中的直接访问和内部访问?

我唯一想到的就是抛出一个错误,捕获它并分析它的堆栈。尽管如此,这似乎是一种解决方法,而不是实际的解决方案,所以我想避免它,除非没有其他办法。

4

2 回答 2

1

正如 torazaburo 在评论中所建议的那样,一种可能的解决方案是为处理程序中的indexOf属性返回一个不同的函数,get并在那里进行必要的操作。具体来说,我们可以让indexOf()方法在原始数组上工作,而不是代理;并添加1到结果中。

if (property === 'indexOf') {
  return (...args) => {
    const result = Reflect.apply(target.indexOf, target, args)
    return result === -1 ? result : result + 1
  }
}

工作代码片段:

const arr = ['a', 'b', 'c']
const p = new Proxy(arr, {
  get: function(target, property, receiver) {
    if (property === 'indexOf') {
      return (...args) => {
        const result = Reflect.apply(target.indexOf, target, args)
        return result === -1 ? result : result + 1
      }
    }
    const parsed = parseInt(property, 10)
    if (!Number.isNaN(parsed)) return target[parsed - 1]
    return target[property]
  }
})
console.log(p.indexOf('c'))

其他数组方法可以类推固定。

于 2016-08-12T14:01:16.877 回答
1

似乎indexOf()内部检查了length属性,然后将数组从 index 迭代0length - 1.

是的。这是所有内置数组方法的行为。

如何区分代理获取处理程序中的直接访问和内部访问?

你不能。

如果我知道该属性是直接访问还是内部访问,那么解决这个问题将是微不足道的。

不,这是错误的方法。如果您希望forEach其行为与正常循环不同,那么您的语义就会出现问题。也许您实际上也想拦截该.length属性?还是环绕索引0?在不知道您要解决的问题的情况下,我们几乎无法提出任何有用的建议。

一种极端的措施是编写自己的所有数组方法版本来处理单索引数组。

于 2016-08-12T13:49:04.947 回答