javascript - es6 - ¿Puedo extender Proxy con una clase ES2015?
javascript reflect (6)
Babel no admite Proxy, simplemente porque no puede. Así que hasta que los navegadores agreguen soporte, no existe.
De la documentación de Babel: "Característica no admitida Debido a las limitaciones de ES5, los proxies no pueden ser transpilados o rellenados"
Intenté extender Proxy, así:
class ObservableObject extends Proxy {}
Usé a Babel para trasladarlo a ES5, y obtuve este error en el navegador:
app.js:15 Uncaught TypeError: Object prototype may only be an Object or null: undefined
Miré la línea de código que señalaba. Aquí está esa parte del código con flechas que apuntan a la línea de código ofensiva:
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);
¿Alguien sabe por qué podría estar recibiendo este error? ¿Es esto un error en Babel? ¿Qué se supone que debe pasar cuando intentas extender Proxy?
Bueno, me había olvidado de esta pregunta, pero alguien recientemente la votó. Aunque técnicamente no puede extender un proxy, hay una manera de forzar a una clase a crear una instancia como proxy y forzar a todas sus subclases a crear una instancia de proxy con las mismas funciones de descriptor de propiedades (solo he probado esto en 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;
De @John L. auto respuesta:
Dentro del constructor podemos usar Proxy para envolver la instancia recién creada. No hay necesidad de extender Proxy.
Ejemplo, proporcione un punto observado de una clase de punto existente:
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
}
})
}
}
prueba:
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)
No, una clase ES2015 no puede extender Proxy
1 .
Los objetos proxy tienen una semántica muy atípica y se consideran "objetos exóticos" en ES2015, lo que significa que "no tienen el comportamiento predeterminado para uno o más de los métodos internos esenciales que deben ser compatibles con todos los objetos". No tienen ningún prototipo, que es donde normalmente obtendría la mayor parte del comportamiento para un tipo que está extendiendo. De la sección 26.2.2: "Propiedades del Proxy Constructor" en la especificación :
El constructor de
Proxy
no tiene una propiedad deprototype
porque los objetos exóticos de proxy no tienen una ranura interna [[Prototype]] que requiere inicialización.
Esto no es una limitación de Babel. Si intentas extender Proxy
en Chrome, donde tanto la sintaxis de clase como la son soportadas de forma nativa, aún obtendrás un error similar:
No se detectó TypeError: la clase extiende el valor no tiene una propiedad de prototipo válida no definida
1 "No" es la respuesta práctica. Sin embargo, Alexander O''Mara señaló que si asigna un valor a Proxy.prototype
(¡bruto!), Es posible extenderlo, al menos en algunos navegadores. Experimentamos con esto un poco . Debido al comportamiento de las instancias de Proxy exóticas, esto no se puede usar para lograr mucho más de lo que podría hacer con una función que envuelve al constructor, y algunos comportamientos no parecen ser consistentes entre los navegadores (no estoy seguro de lo que espera la especificación Si haces esto). Por favor, no intente nada como esto en código serio.
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 es una especie de MyProxy
y fue extendido por A
de clase simultáneamente. Un no es un prototipo original, fue una especie de proxy.
class c1 {
constructor(){
this.__proto__ = new Proxy({}, {
set: function (t, k, v) {
t[k] = v;
console.log(t, k, v);
}
});
}
}
d = nuevo c1 (); da = 123;