#define BUILDING_NODE_EXTENSION#include <node.h>using namespace v8;Handle<Value> RunCallback(const Arguments& args) { HandleScope scope; Local<Function> cb = Local<Function>::Cast(args[0]); const unsigned argc = 1; Local<Value> argv[argc] = { Local<Value>::New(String::New("hello world")) }; cb->Call(Context::GetCurrent()->Global(), argc, argv); return scope.Close(Undefined());}void Init(Handle<Object> exports, Handle<Object> module) { module->Set(String::NewSymbol("exports"), FunctionTemplate::New(RunCallback)->GetFunction());}NODE_MODULE(addon, Init)
主要是第十二行 cb->Call(Context::GetCurrent()->Global(), argc, argv);
。
V8EXPORT Local
v8::Function::Call ( Handle< Object > recv, int argc, Handle< Value > argv[] )
第一个参数是 Handle<Object> recv
。
求问这个参数是干吗用的?什么意思?它调用的时候为什么要用 Context::GetCurrent()->Global()
?
解决方案
唔,其实答案还是在源码V8.h里,1720行起。
/** * A JavaScript function object (ECMA-262, 15.3). */class Function : public Object { public: V8EXPORT Local<Object> NewInstance() const; V8EXPORT Local<Object> NewInstance(int argc, Handle<Value> argv[]) const; V8EXPORT Local<Value> Call(Handle<Object> recv, int argc, Handle<Value> argv[]); V8EXPORT void SetName(Handle<String> name); V8EXPORT Handle<Value> GetName() const;};
那么V8::Function::Call
的接口和ECMA-262里的定义15.3里的[[Call]]
是一致的。
注意,[[Call]]
(15.3.4.5.1)的定义和Function.prototype.call
(15.3.4.4)的定义完全不一样的。[[Call]]
是Function.prototype.call
(及其他几乎所有ECMA-262中定义的Function.prototype
)的实现过程中需要调用的内部方法。
15.3.4.5.1 [[Call]]
When the [[Call]] internal method of a function object, F
, which was created using the bind function is called with a this
value and a list of arguments ExtraArgs
, the following steps are taken:
- Let
boundArgs
be the value of F’s [[BoundArgs]] internal property. - Let
boundThis
be the value of F’s [[BoundThis]] internal property. - Let
target
be the value of F’s [[TargetFunction]] internal property. - Let
args
be a new list containing the same values as the listboundArgs
in the same order followed by the same values as the listExtraArgs
in the same order. - Return the result of calling the [[Call]] internal method of
target
providingboundThis
as thethis
value and providingargs
as the arguments.
所以第一个参数就是执行上下文,用于确定代码执行时的this
。
然后LZ给的源码,其实就是把全局作用域当做this传进了Call而已,作用是在全局作用域里面调用自身(上下文中的cb)。