关于正则表达式和盒装基元的代理

时间:2016-04-04 04:15:49

标签: ecmascript-6

让我说我有一个正在通过代理处理的正则表达式(为了捕获属性访问等):

proxy = new Proxy(/x/, {});

但是当我尝试使用代理作为正则表达式时:

proxy.test('x')

我得到了

  

Uncaught TypeError: Method RegExp.prototype.test called on incompatible receiver [object Object]

'x'.match(proxy)发生了类似的错误。

或者考虑代理一个盒装原语:

proxy = new Proxy(Object(5), {});

但是当我尝试将代理用作表达式的一部分时,期望值为6

proxy + 1

我得到了

  

Uncaught TypeError: Number.prototype.valueOf is not generic(…)

所以我的问题是:

  1. 我是否可以代理正则表达式,使代理功能正如regexp在regexp.test等构造中所做的那样?

  2. 我能否以valueOf行为继续有效的方式代理盒装基元?

1 个答案:

答案 0 :(得分:4)

内置类型/对象可以有所谓的"内部插槽"携带无法从外部访问的状态。有些方法依赖于这种状态,因此如果它缺失则无法运行。

当代理对象时,无法通过标准方法访问这些内部插槽。查看规范,您将经常遇到"如果X没有[[y]]内部槽,则抛出TypeError异常" 。这就是为什么代理内置类型通常不能按预期工作的原因。出于同样的原因,您无法执行Number.prototype.valueOf.call({})

之类的操作

解决方法是将函数直接绑定到代理的目标:

var proxy = new Proxy(/x/, {
  get: function(target, key) {
    if (typeof target[key] === 'function') {
      return target[key].bind(target);  
    }

    return target[key];
 }
});

此示例在每次调用时创建一个新函数。更复杂的解决方案将缓存函数并仅为有问题的方法创建新函数。