从构造函数获取原型而不在v8中创建实例

时间:2014-09-10 00:25:07

标签: c++ node.js v8

我正在编写一个导出对象构造函数的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);
}

是否可以从prototypeFunctionTemplate获取constructor个对象,以便在我获得obj的{​​{1}}新实例时, MyObject会与obj->GetPrototype()进行比较吗?

我尝试使用prototypetpl->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的临时实例的情况下不会收到错误?

1 个答案:

答案 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);