JavaScriptCore C API 詳細解析git
JavaScriptCore介紹github
JavaScriptCore 是 JavaScript 引擎,一般會被叫作虛擬機,專門設計來解釋和執行 JavaScript 代碼,能夠理解爲一個瀏覽器的運行內核。api
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 C API 部分包含六個類 下面咱們詳細解釋每一個類的做用及用法函數
JSBase.h測試
定義了 JavaScriptCore 接口文件 ,主要提供了三個方法this
//檢查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);
複製代碼
JSContextRef.hlua
主要提供 JS 執行所需全部資源和環境spa
//獲取全局的 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 的環境 簡單類比 JSContext
JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass);//crete
JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClassRef globalObjectClass);//CreateInGroup
void JSGlobalContextRelease(JSGlobalContextRef ctx);//relase
JSGlobalContextRef JSGlobalContextRetain(JSGlobalContextRef ctx);//retain
複製代碼
JSObjectRef.h
是一個 JavaScript 對象,主要提供了兩部分API,一部分是建立 JS 對象,還有一部分是給建立的 JS 對象添加對應的 Callback。
Functions
// 建立 JavaScript 類 JSClassCreate JSClassRelease JSClassRetain
JSClassRef JSClassCreate(const JSClassDefinition *definition);
JSObjectMake //建立 JavaScript 對象
JSObjectMakeArray //建立數組
JSObjectMakeConstructor
JSObjectMakeDate 、
JSObjectMakeError
JSObjectMakeFunction
JSObjectMakeRegExp
//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 JSObjectSetPrivate
JSObjectGetProperty JSObjectSetProperty
JSObjectGetPrototype JSObjectSetPrototype
JSObjectGetPropertyAtIndex JSObjectSetPropertyAtIndex
//對 JS 對象的屬性名的操做
JSPropertyNameArrayRetain
JSPropertyNameArrayRelease
JSPropertyNameArrayGetNameAtIndex
JSPropertyNameArrayGetCount
JSPropertyNameAccumulatorAddName
//JS對象條件判斷
JSObjectHasProperty //是否有屬性
JSObjectIsFunction // 是不是一個方法
JSObjectIsConstructor // 是不是構造函數
複製代碼
callBacks
在建立一個JS對象的同時,能夠給該對象設置對應的callback,例如能夠在先建立一個functionJSObjectMakeFunction,同時設置該方法被調用的callback JSObjectCallAsFunctionCallback最後調用該方法 JSObjectCallAsFunction此時callback設置的方法就會響應
上述全部建立對象的方法都有對應的callback能夠設置,咱們能夠靈活的使用這些方法
如
Type Alias JSObjectCallAsConstructorCallback //當該對象被座位構造函數調用是響應callback
typedef JSObjectRef (*JSObjectCallAsConstructorCallback)(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception);
JSObjectCallAsFunctionCallback
typedef JSValueRef (*JSObjectCallAsFunctionCallback)(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception);
複製代碼
JSValueRef.h
一個 JavaScript 值,提供用Object-C的基礎數據類型來建立 JS 的值,或者將JS 的值轉變爲OC的基礎數據類型
//獲取JavaScript值類型
JSValueGetType
//OC基礎數據建立JS的值
JSValueCreateJSONString
JSValueMakeBoolean
JSValueMakeFromJSONString
JSValueMakeNull
JSValueMakeNumber
JSValueMakeString
JSValueMakeUndefined
//JS值轉變爲OC基礎數據
JSValueToBoolean
JSValueToNumber
JSValueToObject
JSValueToStringCopy
//存儲JSValue
JSValueProtect
JSValueUnprotect
//比較判斷JavaScript值類型
JSValueIsBoolean
JSValueIsNull
JSValueIsNumber
JSValueIsObject
JSValueIsObjectOfClass
JSValueIsStrictEqual
JSValueIsString
JSValueIsUndefined
JSValueIsEqual
JSValueIsInstanceOfConstructor
複製代碼
JSStringRef.h
JavaScript 對象中字符串對象,公開的api包括以下
JSStringCreateWithCharacters
JSStringCreateWithUTF8CString
JSStringGetCharactersPtr
JSStringGetLength
JSStringGetMaximumUTF8CStringSize
JSStringGetUTF8CString
JSStringIsEqual
JSStringIsEqualToUTF8CString
JSStringRelease
JSStringRetain
複製代碼
JSStringRefCF.h
CFString 與 JavaScript string 相互轉化
CFStringRef JSStringCopyCFString(CFAllocatorRef alloc, JSStringRef string);
JSStringRef JSStringCreateWithCFString(CFStringRef string);
複製代碼
測試Demo
上面介紹完整個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 loader = JSObjectMake(globalContext, loaderClass, (__bridge void *)(self.view));
JSStringRef logFunctionName = JSStringCreateWithUTF8CString("log");
JSObjectSetProperty(globalContext, globalObject, logFunctionName, loader, kJSPropertyAttributeNone, nil);
JSStringRef logCallStatement = JSStringCreateWithUTF8CString("log()");
JSEvaluateScript(globalContext, logCallStatement, 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、callAsFunction
loaderClass 建立一個 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