v8 回调不适用于堆上的 JavaScript 个对象

v8 callback not working with JavaScript objects on the heap

我创建了一个 JavaScript 对象的实例,例如;

myObj1 = new myObject("Object1");

然后我调用一个 node.js c++ 插件,它会回调 Javascript 对象...

myAddon = require('myAddon');
myAddon.greet(myObj1.name);

C++ 回调代码如下所示:

Local<Function> callback = Local<Function>::Cast(args[0]);
Isolate* isolate = args.GetIsolate();
const int argc = 1;
const char *parm = "Hello";
v8::Local<v8::Value> argv[argc] = {  v8::String::NewFromUtf8(isolate, parm) };
callback->Call(isolate->GetCurrentContext()->Global(), argc, argv);

但问题是绑定不会回调到 myObject 的实例,而是似乎回调到基础 JavaScript class。所以没有实例数据。

根据我过去 2 天的阅读,Call() 方法的第一个参数不知何故变成了 v8 中的 "this" 指针。所以我猜问题可能是我使用的是全局上下文

有人知道如何正确回调堆上的 JavaScript 对象吗?

仅当您 调用 形式为 a.b(...)a[c](...) 的方法时才会设置 this 值,其中 a是任何表达式并且 b 是属性名称(或 c 是作为属性名称求值的表达式)并且属性值是函数。

需要解包的内容很多,但基本上它的意思是,当您执行 a.b.c(d) 时,存储在 a.b.c 的函数将被调用,表达式 a.b 的值为在该函数的上下文中绑定到 this

那是唯一一次这种魔法发生。

因此,当您调用 myAddon.greet(myObj1.name) 时,函数 greet(从对象 myAddon 获取)被调用,this 被设置为 myAddon .没有其他魔法发生。特别是, myObj1.name 被评估,发现是一个函数,并且这个函数对象作为参数传递。 未保留从 myObj1 获取函数的详细信息, 这意味着您的 C++ 代码没有可用于获取对该对象的引用的机制!

相反,在 JavaScript 中执行此操作的正确方法是让代码传递回调以根据需要绑定 this,使用函数的 bind() 方法,如下所示:

myAddon.greet(myObj1.name.bind(myObj1));

您的 C++ 代码将收到一个代理函数对象(bind() 创建一个新函数)。此代理将调用 myObj1.name 函数并将 this 设置为 myObj1,因此您的 C++ 代码根本不必关心它。

为了说明,表达式 myObj1.name.bind(myObj1) 大致等同于

(function (o, f) {
    return function () { return f.apply(o, arguments); };
}(myObj1, myObj1.name))