2017-05-21 28 views
1

注意:这不是关于最佳实践的问题。显然,我们应该避免在常规的JS用法中使用with statement。我对它的行为感兴趣,因为我正在编写一个简单的DSL,并了解如何推动JavaScript的限制来使某些功能发挥作用。拦截财产查找/检查的方法?


考虑下面的代码:

var obj = {prop:0}; 
with(obj) { prop = 1; } 
// obj.prop === 1 

每当我们使用with块(如prop,以上)内的变量,它首先会检查是否该变量是obj属性。如果是,那么它基本上将该变量转换为obj.prop

但是,如果变量并不在obj找到,那么JS引擎冲浪了寻找prop作用域链,直到到达全局对象作为最后一招:

var obj = {}; 
with(obj) { prop = 1; } 
// obj.prop === undefined 
// window.prop === 1 

我的问题是:在上例中,JS引擎在obj内查找prop。有没有办法拦截这个查询?我想“欺骗”JS引擎(当然是以一种符合规范的方式),因为认为obj具有所有属性,因此所有使用with语句的变量都被解释为obj.variable。基本上,我想这种行为:

var obj = {}; 
with(obj) { prop = 1; } 
// obj.prop === 1 

我想这将是作为代理obj和拦截get S作为简单,因为(我想)发动机会做一个get看到的是objprop。我以为我可以简单地返回其他的东西比undefined,然后with会像对待obj具有所有属性:

var prox = new Proxy({}, { 
    set(target, property, value) { target[property] = value; }, 
    get(target, property) { return target[property] !== undefined ? target[property] : null; }, 
}); 
with(prox) { prop = 1; } 

但是,这似乎并没有工作。有任何想法吗?

+0

所以你真的没有问题吗? – trincot

+0

我有一个问题和答案;) – JoeRocc

+0

看看[这个](http://stackoverflow.com/a/41050254/1048572) – Bergi

回答

0

在写这个问题时,我发现的has陷阱,这是我的问题的答案。因此,这里是你如何实现我一直在寻找的行为:

var prox = new Proxy({}, { 
    has(target, property) { return true; }, 
}); 
with(prox) { prop = 1; } 
// prox.prop === 1 

编辑:只是一张纸条,上面这些黑暗的艺术玩了会导致Chrome的DevTools到crash in certain situations。以防止任何人调试时间。

+1

对于那些有兴趣,这是因为['GetIdentifierReference'](https:/ /www.ecma-international.org/ecma-262/7.0/#sec-getidentifier参考),第3步。它检查环境记录是否具有与该名称的绑定,这在对象环境记录的情况下意味着检查[财产存在](https://www.ecma-international.org/ecma-262/7.0/#sec-object-environment-records-hasbinding-n)。 –

+0

MDN在[* Poxy * object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy)上有一些有用的信息,例如在IE中不支持。 – RobG