我正在编写一个导出对象构造函数的v8节点扩展,如this documentation所示。一些函数将其他类的实例作为参数,因此我想检查这些参数的类型,类似于this answer建议的类型。它建议的一件事是将对象的原型与来自临时实例的已知正确原型进行比较,例如
Local<Object> obj = constructor->NewInstance(); prototype = Persistent<Value>::New(obj->GetPrototype()); if (instance->GetPrototype() == prototype) { //...
但是,我的一些构造函数很复杂,并且将其他类的实例作为参数,因此这将非常不方便。
我的类初始化函数看起来像这样(取自链接模板):
void MyObject::Init(Handle<Object> exports) {
// Prepare constructor template
Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
tpl->SetClassName(String::NewSymbol("MyObject"));
tpl->InstanceTemplate()->SetInternalFieldCount(1);
// Prototype
tpl->PrototypeTemplate()->Set(String::NewSymbol("plusOne"),
FunctionTemplate::New(PlusOne)->GetFunction());
constructor = Persistent<Function>::New(tpl->GetFunction());
exports->Set(String::NewSymbol("MyObject"), constructor);
}
是否可以从prototype
或FunctionTemplate
获取constructor
个对象,以便在我获得obj
的{{1}}新实例时, MyObject
会与obj->GetPrototype()
进行比较吗?
我尝试使用prototype
和tpl->PrototypeTemplate()->NewInstance()
,但似乎都没有正确的值。
这是我想要做的完整示例:
constructor->GetPrototype()
目前,如果我在节点中运行以下代码(在构建插件之后),我会收到类型错误:
#include <node.h>
#include <v8.h>
using namespace v8;
class MyObject : public node::ObjectWrap {
public:
static void Init(Handle<Object> exports);
static Persistent<Value> prototype;
private:
static Handle<Value> New(const v8::Arguments& args);
static Handle<Value> TypeTest(const v8::Arguments& args);
static Persistent<Function> constructor;
};
Persistent<Function> MyObject::constructor;
Persistent<Value> MyObject::prototype;
void MyObject::Init(Handle<Object> exports) {
Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
tpl->SetClassName(String::NewSymbol("MyObject"));
tpl->InstanceTemplate()->SetInternalFieldCount(1);
tpl->PrototypeTemplate()->Set(
String::NewSymbol("typeTest"),
FunctionTemplate::New(TypeTest)->GetFunction());
constructor = Persistent<Function>::New(tpl->GetFunction());
prototype = Persistent<Value>::New(tpl->PrototypeTemplate()->NewInstance());
exports->Set(String::NewSymbol("MyObject"),
constructor);
}
Handle<Value> MyObject::New(const Arguments& args) {
HandleScope scope;
if (args.IsConstructCall()) {
MyObject *obj = new MyObject();
obj->Wrap(args.This());
return args.This();
} else {
return scope.Close(constructor->NewInstance());
}
}
Handle<Value> MyObject::TypeTest(const Arguments& args) {
HandleScope scope;
if(args.This()->GetPrototype() != prototype) {
return ThrowException(Exception::TypeError(
String::New("This should not happen")));
}
return Undefined();
}
NODE_MODULE(hello, MyObject::Init);
有没有办法设置var hello = require('./build/Release/hello');
var obj = new hello.MyObject();
obj.typeTest();
,以便在不构建MyObject::prototype
的临时实例的情况下不会收到错误?
答案 0 :(得分:2)
您是否无法在第一次创建对象时设置静态原型值,而不是在Init
内?像这样:
class MyObject : public node::ObjectWrap {
// ... as before ...
};
Persistent<Function> MyObject::constructor;
Persistent<Value> MyObject::prototype;
void MyObject::Init(Handle<Object> exports)
// ... as before but without setting prototype ...
}
Handle<Value> MyObject::New(const Arguments& args) {
HandleScope scope;
if (args.IsConstructCall()) {
MyObject *obj = new MyObject();
obj->Wrap(args.This());
prototype = Persistent<Value>::New(args.This()->GetPrototype());
return args.This();
} else {
return scope.Close(constructor->NewInstance());
}
}
Handle<Value> MyObject::TypeTest(const Arguments& args) {
HandleScope scope;
if(args.This()->GetPrototype() != prototype) {
return ThrowException(Exception::TypeError(
String::New("This should not happen")));
}
return Undefined();
}
NODE_MODULE(hello, MyObject::Init);