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

v8 callback not working with JavaScript objects on the heap

本文关键字:JavaScript 对象 回调 不适用 适用于 v8      更新时间:2023-10-16

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

myObj1 = new myObject("Object1");

然后我调用一个节点.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 类。所以没有实例数据。

从我过去 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))