with(new Proxy({}, {
  has() { return true },
  get(obj, key, proxy) { return console.log(String(key)) } })
) {
  a--
}


在Chrome中输出:
Symbol(Symbol.unscopables)
a
Symbol(Symbol.unscopables)

在Firefox中的输出:
Symbol(Symbol.unscopables)
Symbol(Symbol.unscopables)
a

据我了解,一种获得与阅读值(value)有关,另一种与分配有关。
a--应该写入读取a的同一位置,这是合乎逻辑的。不,这不对。

但是获得Symbol.unscopables的值(value)两次暗示了我们,可以传递一个对象进行读取,而传递另一个对象进行写入。

这样工作真的是真的吗?规范说明了什么?

实际上,它几乎可以在Chrome和FF中使用-可以从一个对象读取并写入另一个对象,但是它导致不同的结果:

更新:Safari 10仅读取一次。

var a, b, flag = true

with (a = { x: 7 })
  with (b = { x: 4, get [Symbol.unscopables]() { return { x: flag=!flag } } })
    x++

                 // Chrome   FF       Safari   Edge
console.log(a)   // {x:5}    {x:7}    {x:7}    {x:5}
console.log(b)   // {x:4}    {x:8}    {x:5}    {x:4}


PS:Same question in Russian

最佳答案

按照规范,对于@x++,@@ unscopables应该只能读取一次,据我所知。查看https://mail.mozilla.org/pipermail/es-discuss/2017-February/047725.html中的详细信息

因此,Chrome和Firefox在这里都是错误的。 Safari正确无误。

另请参见https://bugzilla.mozilla.org/show_bug.cgi?id=1341061https://bugs.chromium.org/p/v8/issues/detail?id=5992

09-30 12:53