javascript - 区分代理获取处理程序中的直接访问和内部访问

标签 javascript ecmascript-6 es6-proxy

我有一个数组:

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

我使用 get 处理程序为该数组创建一个代理,它将为每个数字 n 返回具有 n - 1 索引的属性。例如,p[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' 时它确实有效——它分别返回 12,但是对于 'c',它返回 -1。事实证明 indexOf() 也会触发 get 处理程序。通过将 console.log(property) 添加到 get 处理程序,我们得到以下 p.indexOf('c') 的输出:

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

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

如果我知道该属性是直接访问(如 p[2])还是在内部访问,那么解决这个问题就很简单了。然后我总是可以返回 target[property] 以进行内部访问(因此代理将是空操作)。

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

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

最佳答案

It seems that indexOf() internally checks the length property, and then iterates the array from index 0 to length - 1.

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

How to distinguish direct access from internal access in Proxy get handler?

你不能。

It would be trivial to fix that if I knew whether the property is accessed directly or internally.

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

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

关于javascript - 区分代理获取处理程序中的直接访问和内部访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38918316/

相关文章:

javascript - html5 javascript 自动播放不适用于 android 4.4

javascript - 尝试掌握 JavaScript 动画的窍门

javascript - Object.assign 和 ... spread 运算符失败无提示,不添加元素

node.js - 汇总后 crypto.createHmac 未定义

javascript - 使用javascript代理拦截方法调用时进行非法调用

javascript - 使用 ES6 代理替换原型(prototype)时超出最大调用堆栈大小

javascript - 如何根据索引号设置选择选项的值?

javascript - 比较用 PHP hash() 和 NodeJS crypto.createHash() 制作的 SHA256

javascript - babel 将 `let` 转换为 `var` ,运行时如何知道它应该取决于 block 作用域

javascript - 在运行时向控制台方法添加动态值,并完整保留原始调用位置和行号