javascript - 当我从中获取值时,我的自定义类代理返回未定义
问题描述
我正在尝试制作一个支持类的代理版本。这包括普通代理不支持的 instanceof。这是我到目前为止所得到的:
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 类本身有关......有谁知道这是否可以修复?
基本上我想制作一个自定义版本的代理,它实际上是一个类的实例,但仍然像代理一样。
编辑:这是我的原始代码:
{
// 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
}
解决方案
Bergi 让我意识到 Proxy 确实支持类,但我使用的 API 存在某种奇怪的错误,我假设这是因为 API 的工作方式。它创建了一个完全隔离的虚拟机(我认为它甚至不是一个实际的节点 js 虚拟机),它是从主节点 js 进程产生的,并且全局以某种方式传递给虚拟机。我猜这与全局传递的方式有关,但我看不出它是如何工作的。
对此的真正答案是代理实际上确实支持类和 instanceof,但在 VM 中 instanceof 和类扩展在内置 API 类上的工作方式并不完全相同。我将不得不想出另一种方法来做我想做的事情。
如果有人想知道我在说什么,我正在尝试在名为“Screeps”的编程游戏中为我自己的代码有效地修改类,该游戏售价 15 美元(因此没有游戏的人无法访问) .
我为我的疏忽而道歉。
推荐阅读
- swiftui - SwiftUI presentationMode.wrappedValue.dismiss() 弹回根目录
- java - 尽管没有更改,但禁用电池优化的权限仍然出现在 Android API 28 上
- c# - 如何使一个布尔值可以跨多个 .cs 文件访问
- lazy-loading - Is there a way to get a border around image with Lazy Load plugin?
- xamarin.ios - 我可以只为特定部分更改标签的色调颜色和字体属性吗?
- javascript - 在 VS Code 菜单栏中添加菜单
- javascript - 超时后如何将按钮恢复到原始状态
- c++ - c++ 代码在 Linux 中的行为与 Windows 不同?
- youtube - YouTube 数据 API v3 未获得正确的订阅人数
- java - 如何使用 JFreeChart 更改 X 标签