我正在使用V8为应用程序添加JavaScript支持。由于各种原因我无法进入,我们需要能够向FunctionTemplate添加方法,并让这些方法出现在已经从它继承的任何FunctionTemplates中。
例如,
v8::Handle<v8::FunctionTemplate> parent;
v8::Handle<v8::FunctionTemplate> child;
child->Inherit(parent);
parent->PrototypeTemplate()->Set(isolate, "someNewMethod", v8::FunctionTemplate::New(...));
不幸的是,我发现当父母被修改时,孩子们只有继承时可用的方法,而且,即使我告诉孩子从父母那里重新学习,仍然没有获得新的方法。
更糟糕的是,如果我有这样的关系:
v8::FunctionTemplate parent, firstChild;
firstChild->Inherit(parent);
parent->PrototypeTemplate()->Set(isolate, "newMethod", FunctionTemplate::New(...));
v8::FunctionTemplate secondChild;
secondChild->Inherit(parent);
然后secondChild
的实例仍然只有[{1}}继承parent
时可用的firstChild
方法。
据我所知,V8可能会积极地优化继承关系;从子FunctionTemplate
实例化的对象不显示原型链,而只是将方法直接绑定到它们。所以,我认为我需要使用Object::SetPrototype
来代替这一点,但我在此处所做的每一次尝试都会导致V8崩溃,创建一个原型链,其中没有任何继承的方法可见,或者具有与FunctionTemplate::Inherit
案例相同的有效行为。
在V8中提供继承方法的可接受标准机制是什么,可以将本机方法添加到超类中?
答案 0 :(得分:2)
一旦实际Function
已从FunctionTemplate
实例化,FunctionTemplate
的其他更改将不再反映在派生对象中。因此,一旦调用Inherit
或NewInstance
,您就无法更改附加到基础FunctionTemplate
的方法。
但是,还有另一种方法可以做到这一点:对于每个本地类,都有一个FunctionTemplate
,然后是一个代理Object
,可以直接在原型链中使用。例如,
v8::Handle<v8::FunctionTemplate> base_tmpl;
v8::Handle<v8::Object> base_proto = base_tmpl->GetFunction()->NewInstance();
v8::Handle<v8::FunctionTemplate> derived_tmpl;
v8::Handle<v8::Object> derived_proto = derived_tmpl->GetFunction()->NewInstance();
derived_proto->SetPrototype(base_proto);
base_proto->Set("methodName", v8::FunctionTemplate::New(...)->GetFunction());
然后,当您想要实例化一个对象时,您可以:
v8::Handle<v8::ObjectTemplate> instance_tmpl;
instance_tmpl->SetInternalFieldCount(1);
v8::Handle<v8::Object> instance = instance_tmpl->NewInstance();
instance->SetInternalField(0, nativeObject);
instance->SetPrototype(derived_proto);
从技术上讲,您只需要实例代理Object
,但仍然使用FunctionTemplate
允许您使用其SetClassName
(对调试很有用)以及{{1 (用于运行时类型检查等)。
答案 1 :(得分:0)
我的经历似乎与你的不同。我确实可以在原型上设置方法,并且它们可以通过继承获得,即使在对孩子调用FunctionTemplate::Inherit
之后添加方法时也是如此。
我的工作测试的完整来源是here,但总结一下......
我创建了parent
类,就像这样......
v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
t->SetClassName(v8::String::NewFromUtf8(isolate, "A_Parent"));
auto proto = t->PrototypeTemplate();
proto->Set(v8::String::NewFromUtf8(isolate, "methodA"), v8::FunctionTemplate::New(isolate, MethodACallback));
然后是继承的child
类......
v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
t->SetClassName(v8::String::NewFromUtf8(isolate, "A_Child"));
t->Inherit(parent);
auto proto = parent->PrototypeTemplate();
proto->Set(v8::String::NewFromUtf8(isolate, "methodB"), v8::FunctionTemplate::New(isolate, MethodBCallback));
// MethodACallback and MethodBCallback just contain a simple std::cout statement.
(您会注意到我在methodB
继承child
后)我正在添加parent
然后我导入A_Child
函数导入全局上下文...
ctx->Global()->Set(v8::String::NewFromUtf8(isolate, "A_Child"), child->GetFunction());
...并编译/运行以下脚本......
"use strict";
var c = new A_Child();
c.methodA();
c.methodB();
哪些输出......
methodA called from [object A_Child]
methodB called from [object A_Child]
我正在使用v8 4.2.0并使用clang 3.3进行编译。在OS X 10.8.5上运行