我正在尝试制作支持类的Proxy版本。这包括普通代理不支持的实例。这是我到目前为止所得到的:
let ClassProxy = function(TargetClass, args) { // A class which creates a Proxy of a class
function extend(sup, base) {
var descriptor = Object.getOwnPropertyDescriptor(
base.prototype, 'constructor'
); // Get the constructor
base.prototype = Object.create(sup.prototype); // Create an object with the super's prototype and apply it to the base's prototype
var handler = {
construct: function(target, args) {
var obj = Object.create(base.prototype);
return this.apply(target, obj, args); // Call the constructor
}, // Construct it
apply: function(target, obj, args) {
let obj1 = Reflect.construct(sup, args, function() {
return obj
}) // Construct
let obj2 = Reflect.construct(base, args, function() {
return obj
})
let proto = Object.getPrototypeOf(obj)
let obj1d = Object.getOwnPropertyDescriptors(Object.getPrototypeOf(obj1))
let obj2d = Object.getOwnPropertyDescriptors(Object.getPrototypeOf(obj2))
for (let k in obj1d) {
let prop = obj1d[k]
Object.defineProperty(proto, k, prop) // Attempt to apply the prototype from the super
}
for (let k in obj2d) {
let prop = obj2d[k]
Object.defineProperty(proto, k, prop) // Attempt to apply the prototype from the base
}
Object.setPrototypeOf(obj, proto)
obj1d = Object.getOwnPropertyDescriptors(obj1)
obj2d = Object.getOwnPropertyDescriptors(obj2)
for (let k in obj1d) {
let prop = obj1d[k]
Object.defineProperty(obj, k, prop) // Attempt to set properties from the super
}
for (let k in obj2d) {
let prop = obj2d[k]
Object.defineProperty(obj, k, prop) // Attempt to set properties from the base
}
return obj
} // The constructor of the ClassProxy
}
var proxy = new Proxy(base, handler); // Create a proxy which is a fake class to create fake classes
descriptor.value = proxy; // Set the value for the constructor to the proxy above
Object.defineProperty(base.prototype, 'constructor', descriptor); // Define the constructor
return proxy;
}
let _Proxy = function() {
return new Proxy(this, args) // Basically just lets me create a proxy with the custom arguments
}
_Proxy.prototype = Object.getPrototypeOf(Proxy) // Apply the prototype of Proxy to _Proxy to allow the constructor to use .prototype
return extend(TargetClass, _Proxy) // Combine the classes
}
ClassProxy.prototype.constructor = ClassProxy // Apply the constructor (calling and using new are the same)
let MyClass = class { // Original class
constructor(myClassName) {
console.log("Constructed MyClass! myClassName: "+myClassName) // Test (definitely works)
this.name = myClassName
}
}
let Haha = new ClassProxy(MyClass, { // A class proxy of the original class
get(obj, key) { // A proxy argument
console.log("Intercepted '"+key+"'!") // When I get "name" it should tell me (it doesn't)
return Reflect.get(obj, key) // Return the real value
}
})
let hahaInstance = new Haha("test") // The class proxy
console.log(hahaInstance.test) // Will put undefined and no "intercepted" message will happen
console.log(hahaInstance instanceof MyClass) // True
console.log(new Proxy(new MyClass("test2")) instanceof MyClass) // False (I want to get around this behavior)
它正常工作并且instanceof工作,但索引该类返回undefined并且不调用代理方法。 Object.getOwnPropertyDescriptors工作,你仍然可以获得这样的价值。它似乎可能与Proxy类本身有关......有谁知道这是否可以修复?
基本上我想制作一个自定义版本的Proxy,它实际上是一个类的实例,但仍然像代理一样。
编辑: 这是我的原始代码:
{
// Creep is a class built into the game which is the entity that does all of the work for you
let creepAPI = {
moveTo: function() {
// Optimized moveTo code (the original code can be slow in some rare cases and doesn't do exactly what I want)
}
}
let _Creep = Creep
Creep.constructor = function(creepId) { // Override the constructor
return new Proxy(new _Creep(creepId), { // Make a proxy for the class
get(real, index) { // Allows me to add custom API functions, etc.
console.log("Index: "+index) // Output the index for testing
if (creepAPI[index]) {
return creepAPI[index]
}
return Reflect.get(real, index) // Get the index from the real creep
}
})
}
console.log(new Creep(otherCreep.id) instanceof _Creep) // otherCreep would be an actual instance of a creep (outputs false on my private server)
// Now to use my api I just make a new creep from the id of the actual creep
}
答案 0 :(得分:0)
Bergi让我意识到代理确实支持类,但我正在使用的API有一些奇怪的错误,我假设是因为API的工作方式。它创建了一个完全隔离的虚拟机(我认为它甚至不是一个实际的节点js VM),它是从主节点js进程生成的,并且全局以某种方式传递给VM。我猜它与全局传递的方式有关,但我看不出它是如何工作的。
真正的答案是Proxies实际上支持类和instanceof,但在VM instanceof和类扩展中,在内置的API类中不能完全相同。我将不得不想出另一种方法来做我想做的事情。
如果有人想知道我在说什么,我正试图在一个名为“Screeps”的编程游戏中为我自己的代码有效地修改类,这个游戏的价格是15美元(所以没有人可以访问游戏)。
我为我的疏忽而道歉。