我可以使用 ES2015 class 扩展 Proxy 吗?
Can I extend Proxy with an ES2015 class?
我试过扩展 Proxy,像这样:
class ObservableObject extends Proxy {}
我使用 Babel 将其转译为 ES5,但在浏览器中出现此错误:
app.js:15 Uncaught TypeError: Object prototype may only be an Object or null: undefined
我查看了它指向的代码行。这是代码的那部分,箭头指向有问题的代码行:
var ObservableObject = exports.ObservableObject = function (_Proxy) {
_inherits(ObservableObject, _Proxy); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
function ObservableObject() {
_classCallCheck(this, ObservableObject);
return _possibleConstructorReturn(this, Object.getPrototypeOf(ObservableObject).apply(this, arguments));
}
return ObservableObject;
}(Proxy);
有谁知道我为什么会收到此错误?这是 Babel 中的错误吗?当您尝试扩展 Proxy 时应该发生什么?
Babel 不支持 Proxy,原因很简单。所以在浏览器添加支持之前,它不存在。
来自 Babel 文档:
“不支持的功能
由于 ES5 的限制,Proxies 不能被转译或 polyfilled
不,ES2015 class 不能扩展 Proxy
1.
代理对象具有非常不典型的语义,在 ES2015 中被视为“奇异对象”,这意味着它们“不具有所有对象必须支持的一种或多种基本内部方法的默认行为”。它们没有任何原型,您通常会在原型中获得要扩展的类型的大部分行为。来自 section 26.2.2: "Properties of the Proxy Constructor" in the specification:
The Proxy
constructor does not have a prototype
property because proxy exotic objects do not have a [[Prototype]] internal slot that requires initialization.
这不是 Babel 的限制。如果您尝试在 Chrome 中扩展 Proxy
,它和 class 语法均受本地支持,您仍然会收到类似的错误:
Uncaught TypeError: Class extends value does not have valid prototype property undefined
1 “否”是实际的答案。然而,Alexander O'Mara pointed out that if you assign a value to Proxy.prototype
(gross!), it does become possible to extend, at least in some browsers. We experimented with this a little。由于异国情调的代理实例的行为,这不能用来完成比包装构造函数所能做的更多的事情,并且某些行为在浏览器之间似乎不一致(我不确定规范期望什么如果你这样做)。请不要在严肃的代码中尝试这样的事情。
class c1 {
constructor(){
this.__proto__ = new Proxy({}, {
set: function (t, k, v) {
t[k] = v;
console.log(t, k, v);
}
});
}
}
d = 新 c1();
d.a = 123;
好吧,我忘记了这个问题,但最近有人对它投了赞成票。即使您在技术上无法扩展代理,也有一种方法可以强制 class 实例化为代理并强制其所有子 class 实例化为具有相同 [=15= 的代理] 描述符函数(我只在 Chrome 中测试过):
class ExtendableProxy {
constructor() {
return new Proxy(this, {
set: (object, key, value, proxy) => {
object[key] = value;
console.log('PROXY SET');
return true;
}
});
}
}
class ChildProxyClass extends ExtendableProxy {}
let myProxy = new ChildProxyClass();
// Should set myProxy.a to 3 and print 'PROXY SET' to the console:
myProxy.a = 3;
class A { }
class MyProxy {
constructor(value, handler){
this.__proto__.__proto__ = new Proxy(value, handler);
}
}
let p = new MyProxy(new A(), {
set: (target, prop, value) => {
target[prop] = value;
return true;
},
get: (target, prop) => {
return target[prop];
}
});
console.log("p instanceof MyProxy", p instanceof MyProxy); // true
console.log("p instanceof A", p instanceof A); // true
p 是一种 MyProxy
,它同时被 class 的 A
扩展。
A 不是原始原型,它被代理了。
来自@John L. 的自我回复:
在构造函数中,我们可以使用 Proxy 来包装新创建的实例。无需扩展代理。
例如,提供从现有点观察到的点class:
class Point {
constructor(x, y) {
this.x = x
this.y = y
}
get length() {
let { x, y } = this
return Math.sqrt(x * x + y * y)
}
}
class ObservedPoint extends Point {
constructor(x, y) {
super(x, y)
return new Proxy(this, {
set(object, key, value, proxy) {
if (object[key] === value)
return
console.log('Point is modified')
object[key] = value
}
})
}
}
测试:
p = new ObservedPoint(3, 4)
console.log(p instanceof Point) // true
console.log(p instanceof ObservedPoint) // true
console.log(p.length) // 5
p.x = 10 // "Point is modified"
console.log(p.length) // 5
p.x = 10 // nothing (skip)
我试过扩展 Proxy,像这样:
class ObservableObject extends Proxy {}
我使用 Babel 将其转译为 ES5,但在浏览器中出现此错误:
app.js:15 Uncaught TypeError: Object prototype may only be an Object or null: undefined
我查看了它指向的代码行。这是代码的那部分,箭头指向有问题的代码行:
var ObservableObject = exports.ObservableObject = function (_Proxy) {
_inherits(ObservableObject, _Proxy); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
function ObservableObject() {
_classCallCheck(this, ObservableObject);
return _possibleConstructorReturn(this, Object.getPrototypeOf(ObservableObject).apply(this, arguments));
}
return ObservableObject;
}(Proxy);
有谁知道我为什么会收到此错误?这是 Babel 中的错误吗?当您尝试扩展 Proxy 时应该发生什么?
Babel 不支持 Proxy,原因很简单。所以在浏览器添加支持之前,它不存在。
来自 Babel 文档: “不支持的功能 由于 ES5 的限制,Proxies 不能被转译或 polyfilled
不,ES2015 class 不能扩展 Proxy
1.
代理对象具有非常不典型的语义,在 ES2015 中被视为“奇异对象”,这意味着它们“不具有所有对象必须支持的一种或多种基本内部方法的默认行为”。它们没有任何原型,您通常会在原型中获得要扩展的类型的大部分行为。来自 section 26.2.2: "Properties of the Proxy Constructor" in the specification:
The
Proxy
constructor does not have aprototype
property because proxy exotic objects do not have a [[Prototype]] internal slot that requires initialization.
这不是 Babel 的限制。如果您尝试在 Chrome 中扩展 Proxy
,它和 class 语法均受本地支持,您仍然会收到类似的错误:
Uncaught TypeError: Class extends value does not have valid prototype property undefined
1 “否”是实际的答案。然而,Alexander O'Mara pointed out that if you assign a value to Proxy.prototype
(gross!), it does become possible to extend, at least in some browsers. We experimented with this a little。由于异国情调的代理实例的行为,这不能用来完成比包装构造函数所能做的更多的事情,并且某些行为在浏览器之间似乎不一致(我不确定规范期望什么如果你这样做)。请不要在严肃的代码中尝试这样的事情。
class c1 {
constructor(){
this.__proto__ = new Proxy({}, {
set: function (t, k, v) {
t[k] = v;
console.log(t, k, v);
}
});
}
}
d = 新 c1(); d.a = 123;
好吧,我忘记了这个问题,但最近有人对它投了赞成票。即使您在技术上无法扩展代理,也有一种方法可以强制 class 实例化为代理并强制其所有子 class 实例化为具有相同 [=15= 的代理] 描述符函数(我只在 Chrome 中测试过):
class ExtendableProxy {
constructor() {
return new Proxy(this, {
set: (object, key, value, proxy) => {
object[key] = value;
console.log('PROXY SET');
return true;
}
});
}
}
class ChildProxyClass extends ExtendableProxy {}
let myProxy = new ChildProxyClass();
// Should set myProxy.a to 3 and print 'PROXY SET' to the console:
myProxy.a = 3;
class A { }
class MyProxy {
constructor(value, handler){
this.__proto__.__proto__ = new Proxy(value, handler);
}
}
let p = new MyProxy(new A(), {
set: (target, prop, value) => {
target[prop] = value;
return true;
},
get: (target, prop) => {
return target[prop];
}
});
console.log("p instanceof MyProxy", p instanceof MyProxy); // true
console.log("p instanceof A", p instanceof A); // true
p 是一种 MyProxy
,它同时被 class 的 A
扩展。
A 不是原始原型,它被代理了。
来自@John L. 的自我回复:
在构造函数中,我们可以使用 Proxy 来包装新创建的实例。无需扩展代理。
例如,提供从现有点观察到的点class:
class Point {
constructor(x, y) {
this.x = x
this.y = y
}
get length() {
let { x, y } = this
return Math.sqrt(x * x + y * y)
}
}
class ObservedPoint extends Point {
constructor(x, y) {
super(x, y)
return new Proxy(this, {
set(object, key, value, proxy) {
if (object[key] === value)
return
console.log('Point is modified')
object[key] = value
}
})
}
}
测试:
p = new ObservedPoint(3, 4)
console.log(p instanceof Point) // true
console.log(p instanceof ObservedPoint) // true
console.log(p.length) // 5
p.x = 10 // "Point is modified"
console.log(p.length) // 5
p.x = 10 // nothing (skip)