- Notifications
You must be signed in to change notification settings - Fork4
JavaScriptCore-C接口详解,以及基本的使用方法
Richard-zhang-iOS/JavaScriptCore-usage
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
JavaScriptCore 是 JavaScript 引擎,通常会被叫做虚拟机,专门设计来解释和执行 JavaScript 代码,可以理解为一个浏览器的运行内核。
JavaScriptCore Framework 是 iOS7 引入的新功能,其实就是基于 Webkit 中以 C/C++ 实现的 JavaScriptCore 的一个封装,大多数 iOS 比较熟悉的是它的 Objective-C API,可以用简洁的方式实现 JS 与Native 交互,其实它还有C API的部分,虽然也是开源的,但是在查看源代码时只有较少的介绍,而且我们知道 Objective-C API 只是 C API 接口的封装。本文主要介绍 C API 部分,帮助大家更好理解 JavaScriptCore Framework。
JavaScriptCore C API 部分包含六个类 下面我们详细解释每个类的作用及用法
JavaScriptCore 的接口文件,这个类中 import 了其他的类,简单封装了其他的 C API。
JSContextRef 相当于 Objective-C 中的 JSContext,主要提供 JS 执行的上下文环境。
JSObjectRef 相当于 Objective-C 中的 JSObject,它代表一个JavaScript对象,交互的核心都在这个类中实现。
是 JavaScript 中基本的字符串表示形式。
包含 CFString 便利的方法。
JSValueRef 相当于 Objective-C 中的 JSValue ,对应一个 JavaScript 的值,它是所有JavaScript值的基本类型
定义了 JavaScriptCore 接口文件 ,主要提供了三个方法
//检查JavaScript 字符串中的语法错误。bool JSCheckScriptSyntax(JSContextRef ctx, JSStringRef script, JSStringRef sourceURL, int startingLineNumber, JSValueRef *exception);//执行一段js语句JSValueRef JSEvaluateScript(JSContextRef ctx, JSStringRef script, JSObjectRef thisObject, JSStringRef sourceURL, int startingLineNumber, JSValueRef *exception);//执行JavaScript GC 在JavaScript执行期间,一般不需要调用此函数; JavaScript 引擎将根据需要进行垃圾回收,在释放对上下文组的最后一个引用时,将自动销毁在上下文组中创建的JavaScript值。void JSGarbageCollect(JSContextRef ctx);
主要提供 JS 执行所需所有资源和环境
//获取全局的 globalObject 对象,该对象将全局的 JavaScript 设置为跟对象,因此我们可以将我们自己的对象定义为 JavaScript 执行环境。JSObjectRef JSContextGetGlobalObject(JSContextRef ctx);// contextGroup 对象提供了虚拟机的功能 简单类比 JSVirtualMachine 但是需要自己管理内存。JSContextGroupRef JSContextGetGroup(JSContextRef ctx);JSContextGroupRef JSContextGroupCreate(void);void JSContextGroupRelease(JSContextGroupRef group);JSContextGroupRef JSContextGroupRetain(JSContextGroupRef group);//globalContext对象是提供执行 js 的环境 简单类比 JSContextJSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass);//creteJSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClassRef globalObjectClass);//CreateInGroupvoid JSGlobalContextRelease(JSGlobalContextRef ctx);//relaseJSGlobalContextRef JSGlobalContextRetain(JSGlobalContextRef ctx);//retain
是一个 JavaScript 对象,主要提供了两部分API,一部分是创建 JS 对象,还有一部分是给创建的 JS 对象添加对应的 Callback。
// 创建 JavaScript 类 JSClassCreate JSClassRelease JSClassRetainJSClassRef JSClassCreate(const JSClassDefinition *definition);JSObjectMake //创建 JavaScript 对象JSObjectMakeArray //创建数组JSObjectMakeConstructorJSObjectMakeDate 、JSObjectMakeErrorJSObjectMakeFunctionJSObjectMakeRegExp//JavaScript 对象作为构造函数来调用JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception);//JavaScript 对象作为方法来调用JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception);JSObjectCopyPropertyNames //获取对象的所有可枚举属性JSObjectDeleteProperty //从对象中删除属性//对 JS 对象的 Private、Property、Prototype 操作JSObjectGetPrivate JSObjectSetPrivateJSObjectGetProperty JSObjectSetPropertyJSObjectGetPrototype JSObjectSetPrototypeJSObjectGetPropertyAtIndex JSObjectSetPropertyAtIndex//对 JS 对象的属性名的操作JSPropertyNameArrayRetainJSPropertyNameArrayReleaseJSPropertyNameArrayGetNameAtIndexJSPropertyNameArrayGetCountJSPropertyNameAccumulatorAddName//JS对象条件判断JSObjectHasProperty //是否有属性JSObjectIsFunction // 是否是一个方法JSObjectIsConstructor // 是否是构造函数
在创建一个JS对象的同时,可以给该对象设置对应的callback,例如可以在先创建一个functionJSObjectMakeFunction
,同时设置该方法被调用的callbackJSObjectCallAsFunctionCallback
最后调用该方法JSObjectCallAsFunction
此时callback设置的方法就会响应
上述所有创建对象的方法都有对应的callback可以设置,我们可以灵活的使用这些方法
如
Type Alias JSObjectCallAsConstructorCallback //当该对象被座位构造函数调用是响应callbacktypedef JSObjectRef (*JSObjectCallAsConstructorCallback)(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception);JSObjectCallAsFunctionCallbacktypedef JSValueRef (*JSObjectCallAsFunctionCallback)(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception);
一个 JavaScript 值,提供用Object-C的基础数据类型来创建 JS 的值,或者将JS 的值转变为OC的基础数据类型
//获取JavaScript值类型JSValueGetType//OC基础数据创建JS的值JSValueCreateJSONStringJSValueMakeBooleanJSValueMakeFromJSONStringJSValueMakeNullJSValueMakeNumberJSValueMakeStringJSValueMakeUndefined//JS值转变为OC基础数据JSValueToBooleanJSValueToNumberJSValueToObjectJSValueToStringCopy//存储JSValueJSValueProtectJSValueUnprotect//比较判断JavaScript值类型JSValueIsBooleanJSValueIsNullJSValueIsNumberJSValueIsObjectJSValueIsObjectOfClassJSValueIsStrictEqualJSValueIsStringJSValueIsUndefinedJSValueIsEqualJSValueIsInstanceOfConstructor
JavaScript 对象中字符串对象,公开的api包括如下
JSStringCreateWithCharacters JSStringCreateWithUTF8CStringJSStringGetCharactersPtrJSStringGetLengthJSStringGetMaximumUTF8CStringSizeJSStringGetUTF8CStringJSStringIsEqualJSStringIsEqualToUTF8CStringJSStringReleaseJSStringRetain
CFString 与 JavaScript string 相互转化
CFStringRef JSStringCopyCFString(CFAllocatorRef alloc, JSStringRef string);JSStringRef JSStringCreateWithCFString(CFStringRef string);
上面介绍完整个JavaScriptCore C API部分,下面我们通过一个demo来详细分析如何使用这些api
#import "ViewController.h"#import <JavaScriptCore/JavaScriptCore.h>JSValueRef ObjectGetPropertyCallback(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef *exception){ NSLog(@"ObjectGetPropertyCallback"); return nil;};JSValueRef ObjectCallAsFunctionCallback(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { NSLog(@"ObjectCallAsFunctionCallback"); return JSValueMakeUndefined(ctx);}void ObjectConstructorFinalize(JSObjectRef object) { NSLog(@"ObjectConstructorFinalize");}bool ObjectConstructorHasInstance(JSContextRef ctx, JSObjectRef constructor, JSValueRef possibleInstance, JSValueRef* exception) { NSLog(@"ObjectConstructorHasInstance"); return nil;}JSObjectRef ObjectCallAsConstructor(JSContextRef ctx, JSObjectRef constructor, size_t argc, const JSValueRef argv[], JSValueRef* exception) { NSLog(@"ObjectCallAsConstructor"); return nil;}@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; JSContextGroupRef contextGroup = JSContextGroupCreate(); JSGlobalContextRef globalContext = JSGlobalContextCreateInGroup(contextGroup, nil); JSObjectRef globalObject = JSContextGetGlobalObject(globalContext); JSClassDefinition constructorClassDef = kJSClassDefinitionEmpty; constructorClassDef.getProperty = ObjectGetPropertyCallback; constructorClassDef.callAsFunction = ObjectCallAsFunctionCallback; constructorClassDef.callAsConstructor = ObjectCallAsConstructor; constructorClassDef.hasInstance = ObjectConstructorHasInstance; constructorClassDef.finalize = ObjectConstructorFinalize; JSClassRef loaderClass = JSClassCreate(&constructorClassDef); JSObjectRef globalObject = JSContextGetGlobalObject(globalContext); JSStringRef logFunctionName = JSStringCreateWithUTF8CString("log"); JSObjectRef functionObject = JSObjectMakeFunctionWithCallback(globalContext, logFunctionName, &ObjectCallAsFunctionCallback); JSObjectSetProperty(globalContext, globalObject, logFunctionName, functionObject, kJSPropertyAttributeNone, nil); JSStringRef logCallStatement = JSStringCreateWithUTF8CString("log()"); JSEvaluateScript(globalContext, logCallStatement, nil, nil, 1,nil); JSObjectRef loader = JSObjectMake(globalContext, loaderClass, (__bridge void *)(self.view)); JSStringRef myclass = JSStringCreateWithUTF8CString("myclass"); JSObjectSetProperty(globalContext, globalObject, myclass, loader, kJSPropertyAttributeNone, nil); JSStringRef callMyclass = JSStringCreateWithUTF8CString("myclass.start()"); JSEvaluateScript(globalContext, callMyclass, nil, nil, 1,nil); /* memory management code to prevent memory leaks */ JSGlobalContextRelease(globalContext); JSContextGroupRelease(contextGroup); JSStringRelease(logFunctionName); JSStringRelease(logCallStatement);}
执行结果
2018-07-02 20:29:47.485072+0800 ObjectCallAsFunctionCallback
2018-07-02 20:29:47.485290+0800 ObjectGetPropertyCallback
2018-07-02 20:29:47.489448+0800 ObjectConstructorFinalize
下面我们详细分析这段代码
contextGroup 是JS执行的虚拟机,后续所有的一切基于它来进行globalContext 是JavaScript的执行环境,第一个参数数虚拟机,第二个参数是nil,是使用默认的类来作为跟对象globalObject 获取全局的 globalObject 对象constructorClassDef 定义一个 JavaScript 类,同时设置该类的特殊事件的callback 如getProperty、callAsFunctionloaderClass 创建一个 JavaScript 类loader 通过 JavaScript 类 创建一个 JavaScript 对象JSObjectSetProperty 给全局的 globalObject 对象设置关联信息 @“log”JSEvaluateScript 执行log方法JSObjectSetProperty 给全局的 globalObject 对象设置class JSEvaluateScript 调用 class 的 方法
github地址:https://github.com/Richard-zhang-iOS/JavaScriptCore-C-Demo 原创不易,欢迎star
About
JavaScriptCore-C接口详解,以及基本的使用方法
Topics
Resources
Uh oh!
There was an error while loading.Please reload this page.