构造函数调用绑定函数的代理
Constructor call to proxy of a bound function
假设我有一个函数 Foo
,我希望从它构造的对象具有 bar
属性:
function Foo() {}
Foo.prototype.bar = 'baz'
console.log('new Foo().bar: ' + new Foo().bar)
new Foo().bar: baz
现在假设我 bind Foo
以某种方式。绑定函数仍然可以在构造函数调用中使用,绑定的this
被忽略:
const Bound = Foo.bind(42)
console.log('new Bound().bar: ' + new Bound().bar)
new Bound().bar: baz
Proxies 应该是通用和透明的。然而...
const PFoo = new Proxy(Foo, { })
console.log('new PFoo().bar: ' + new PFoo().bar)
const PBound = new Proxy(Bound, { })
console.log('new PBound().bar: ' + new PBound().bar)
new PFoo().bar: baz
new PBound().bar: undefined
我希望第二个代理的行为与 Bound
完全相同,因为我使用的是空处理程序。换句话说,我希望最后的输出是 baz
.
为什么不是这样?
(完整片段如下)
function Foo() {}
Foo.prototype.bar = 'baz'
console.log('new Foo().bar: ' + new Foo().bar)
const Bound = Foo.bind(42)
console.log('new Bound().bar: ' + new Bound().bar)
const PFoo = new Proxy(Foo, { })
console.log('new PFoo().bar: ' + new PFoo().bar)
const PBound = new Proxy(Bound, { })
console.log('new PBound().bar: ' + new PBound().bar)
tl;博士
当使用new F
时,new.target
设置为F
除非 F
是绑定函数,在那种情况下new.target
成为原始函数。代理不会发生这种情况。
长答案
好的,我想我明白了。 是一个很好的起点。主要成分:
new.target
- [[原型]] 内部插槽
- 构造函数
prototype
属性
注意:在构造函数调用中,新对象的原型设置为new.target.prototype
。这是 this specification.
的第 5 步
起点:在执行 new F()
、new.target
is initially set to F
时(点击链接)。但是,这可能会在构建过程中发生变化...
new Foo()
没什么奇怪的,new.target
是Foo
,新创建的对象原型是Foo.prototype
。
new Bound()
这很有趣。一开始,new.target
就是Bound
。但是,bound functions [[Construct]] internal method 的第 5 步执行以下操作:如果将 new.target
设置为绑定函数,则将其更改为目标函数,即 Foo
。因此,再次使用Foo.prototype
。
new PFoo()
new.target
始终是 PFoo
,但它是 Foo
的代理,因此当请求 PFoo.prototype
时,再次给出 Foo.prototype
。
new PBound()
new.target
设置为 PBound
。这次调用绑定函数的[[Construct]]内部方法时,new.target
是不等于绑定函数,所以没有改变,我们最终使用 PBound.prototype
,转发到 Bound.prototype
。确实...
function Foo() { }
Foo.prototype.iAm = 'Foo'
const Bound = Foo.bind(42)
Bound.prototype = {iAm: 'Bound'}
const Proxied = new Proxy(Bound, { })
console.log(new Proxied().iAm)
个人意见:我的理解是,在构造绑定函数时,new.target
被更改,以便一切都按预期工作。同样,我希望代理对象的构造在继续之前将 new.target
设置为代理函数。这是一个幼稚的想法,也许还有我没有考虑的极端情况。
假设我有一个函数 Foo
,我希望从它构造的对象具有 bar
属性:
function Foo() {}
Foo.prototype.bar = 'baz'
console.log('new Foo().bar: ' + new Foo().bar)
new Foo().bar: baz
现在假设我 bind Foo
以某种方式。绑定函数仍然可以在构造函数调用中使用,绑定的this
被忽略:
const Bound = Foo.bind(42)
console.log('new Bound().bar: ' + new Bound().bar)
new Bound().bar: baz
Proxies 应该是通用和透明的。然而...
const PFoo = new Proxy(Foo, { })
console.log('new PFoo().bar: ' + new PFoo().bar)
const PBound = new Proxy(Bound, { })
console.log('new PBound().bar: ' + new PBound().bar)
new PFoo().bar: baz
new PBound().bar: undefined
我希望第二个代理的行为与 Bound
完全相同,因为我使用的是空处理程序。换句话说,我希望最后的输出是 baz
.
为什么不是这样?
(完整片段如下)
function Foo() {}
Foo.prototype.bar = 'baz'
console.log('new Foo().bar: ' + new Foo().bar)
const Bound = Foo.bind(42)
console.log('new Bound().bar: ' + new Bound().bar)
const PFoo = new Proxy(Foo, { })
console.log('new PFoo().bar: ' + new PFoo().bar)
const PBound = new Proxy(Bound, { })
console.log('new PBound().bar: ' + new PBound().bar)
tl;博士
当使用new F
时,new.target
设置为F
除非 F
是绑定函数,在那种情况下new.target
成为原始函数。代理不会发生这种情况。
长答案
好的,我想我明白了。
new.target
- [[原型]] 内部插槽
- 构造函数
prototype
属性
注意:在构造函数调用中,新对象的原型设置为new.target.prototype
。这是 this specification.
起点:在执行 new F()
、new.target
is initially set to F
时(点击链接)。但是,这可能会在构建过程中发生变化...
new Foo()
没什么奇怪的,new.target
是Foo
,新创建的对象原型是Foo.prototype
。
new Bound()
这很有趣。一开始,new.target
就是Bound
。但是,bound functions [[Construct]] internal method 的第 5 步执行以下操作:如果将 new.target
设置为绑定函数,则将其更改为目标函数,即 Foo
。因此,再次使用Foo.prototype
。
new PFoo()
new.target
始终是 PFoo
,但它是 Foo
的代理,因此当请求 PFoo.prototype
时,再次给出 Foo.prototype
。
new PBound()
new.target
设置为 PBound
。这次调用绑定函数的[[Construct]]内部方法时,new.target
是不等于绑定函数,所以没有改变,我们最终使用 PBound.prototype
,转发到 Bound.prototype
。确实...
function Foo() { }
Foo.prototype.iAm = 'Foo'
const Bound = Foo.bind(42)
Bound.prototype = {iAm: 'Bound'}
const Proxied = new Proxy(Bound, { })
console.log(new Proxied().iAm)
个人意见:我的理解是,在构造绑定函数时,new.target
被更改,以便一切都按预期工作。同样,我希望代理对象的构造在继续之前将 new.target
设置为代理函数。这是一个幼稚的想法,也许还有我没有考虑的极端情况。