H5与iOS混编 之 JavaScriptCore 详解

一、浏览器历史

浏览器器对于现代社会人来说再普通不过,可对它的历史了解的人却不多。

  • 1990年 Berners-Lee 发明了 WorldWideWeb 浏览器,后改名 Nexus,在1991年公布了源码。

  • 1993年 Marc Andreessen 的团队开发了 Mosaic,1994年推出我们熟悉的 Netscape Navigator 网景浏览器,同时成立了网景公司。

  • 1995年微软推出了 Internet Explorer 浏览器,简称 IE,通过免费绑定进 Windows 95 系统最终替代了 Netscape,赢得了浏览器大战。

  • 1998年网景公司成立了 Mozilla 基金会组织,同时开源浏览器代码,2004年推出有多标签和支持扩展的 Firefox 火狐浏览器开始慢慢的占领市场份额。

  • 2003年苹果发布了 Safari 浏览器,2005年放出了核心源码 WebKit。

  • 2008年 Google 以苹果的 WebKit 为内核,建立了新的项目 Chromium,在此基础上开发了自己浏览器 Chrome。

    浏览器中最核心的部分则是浏览器内核,每个浏览器都有其各自的内核,而对移动领域影响最深的则当属WebKit。

二、WebKit

(关键字:webkit页渲逻处引擎,h/c/js理成可操作web页,含wc、jsc)

WebKit就是一个页面渲染以及逻辑处理引擎,HTML、JavaScript、CSS经过它的处理,成为可见且可操作的Web页面。

WebKit由四个部分组成,分别是:

  • WebKit Embedding API:负责浏览器UI与WebKit进行交互的部分

  • 最核心部分:WebCore和 JavaScriptCore

  • Platform API(WebKit Ports):让Webkit更加方便的移植到各个操作系统、平台上,提供的一些调用Native Library的接口。如在渲染层面,iOS系统中通过Safari的CoreGraphics处理,而Android系统中则是通过Skia处理。

    1.WebKit包括webcore排版引擎和jscore引擎,从KDE的免费软件,根据GPL协议授权,支持BSD系统开发的KHTML和KJS引擎派生出来的。所以WebKit也是免费软件和开源代码;

2.WebKit的优点是高效稳定,兼容性好,源代码结构清晰,易于维护;

3.WebKit内核广泛应用于手机中,如谷歌的Android、苹果的iPhone、诺基亚的sseries60浏览器等WebKit

三、WebCore

WebCore作为WebKit中最核心的渲染引擎,由所有基于WebKit分支开发的浏览器共享,也是WebKit中代码最多的部分。

四、JavaScriptCore简称JSCore开架 iOS7后推出

如React Native、Weex均可在iOS与Android上运行,而在背后支撑它们运行的就是JavaScriptCore(简称JSCore或JSC),为Native 与 JavaScript 建立起通信渠道。

在iOS7以前对JS操作用webView里的函数stringByEvaluatingJavaScriptFromString,而JS对OC的回调基于URL拦截。用的较多的混合开发开源库WebViewJavascriptBridge和EasyJSVebView

iOS7以后导入#import<JavaScriptCore/JavaScriptCore.h>进行JS与原生交互

WebKit的一部分 实现了标准JS语言,没有浏览器对象BOM,也没有window dom XML HTTPRequest

JSCore提供JS和原生交互能力,通过JSCore能更好地两端对象暴露

在原生执行JS,而不用通过浏览器

把原生对象注入到JS环境里去

JavaScriptCore由4部分组成 Lexer(词法分析) - Parser(语法分析) - ByteCodeGenerator(字节码生成) - LLInt & JIT(解释执行)

#import "JSContext.h"         //js上下文,执行js代码
#import "JSValue.h"           //封装js数据类型   
#import "JSManagedValue.h"    //管理JSValue内存
#import "JSVirtualMachine.h"  //JavaScript虚拟机,js底层执行环境
#import "JSExport.h"          //导出OC对象

4.1 JSContext 用到最主要的类

JS执行的环境,同时也通过JSVirtualMachine管理着所有对象的生命周期,每个JSValue都和JSContext相关联并且强引用context。

创建js环境,通过evaluateScript在js环境创建数组,取出数组,注意:evaluate返回的是JSValue,故最后用toString转成字符串类型

JSContext *context = [[JSContext alloc] init];
[context evaluateScript:@"var array = ['a', 'b', 'c']"];
NSString *string = [[context evaluateScript:[NSString stringWithFormat:@"array[%d]", 1]] toString];

4.2 JSValue 一个指向JS值的引用指针

可以是数字、字符串、数组、函数等任何类型,支持以下10种类型互换

Objective-C type | JavaScript type 
-----------------+----------------- 
nil              |     undefined         
NSNull           |     null        
NSString         |     string        
NSNumber         |   number, boolean      
NSDictionary     |   Object object        
NSArray          |    Array object         
NSDate           |     Date object        
NSBlock          |   Function object            
id               |   Wrapper object          
Class            | Constructor object

4.3 JSExport协议(关键字:原实JSE OC对属直给JS )

原生实现JSExport协议,把原生对象的属性和方法直接暴露给JS环境调用

JS与OC交互主要2种方式:(关键字:b闭匿 单法给JS)

Block:block闭包 匿名函数 单个方法暴露给JS

JSExport 协议 : 将OC中某对象直接暴露给JS使用,且在JS中使用就像调用JS的对象一样自然

在 JSContext可注入 Native 对象,也可以直接注入一个 Block:

在原生中写注入Block代码
context[@"log"] = ^(NSString *string) {
    NSLog(@"%@", string);
};
​
在 JS 环境中使用 log("")来输出内容
@protocol UIViewExport <JSExport>
@property (nonatomic, assign) CGFloat alpha;
@end
class_addProtocol(UIView.class, @protocol(UIViewExport));
@protocol NativeObjectExport <JSExport>
@property (nonatomic, assign) BOOL property1;
- (void)method1:(JSValue *)arguments;
@end
​
@interface NativeObject : NSObject<NativeObjectExport>//NativeObject对象可为任意对象
@property (nonatomic, assign) BOOL property1;
@property (nonatomic, strong) id property2;
​
- (void)method1:(JSValue *)arguments;
- (void)method2;
@end
context[@"helper"] = [NativeObject new];
var prop = helper.property1;
helper.method1({
  handler: function(object) {
  }
});
[arguments[@"handler"] callWithArguments:@[object]];

JS 环境通过 function 的 object 拿到返回结果,这就是一个完整的流程。

当 Native 代码执行完 method1 之后,可以通过这个 handler 回调到 JS 环境:

上面的 handler 可以拿来做什么?

JS 环境中可以使用这些方法了:

我们只要在 context 里面注入这么一个对象,就可以在 JS 环境放肆的与 Native 进行交互了:

实现 JSExport 协议,把原生对象的属性和方法暴露给 JS 环境

当我们在 JS 环境里面拿到一个 UIView 时,他的 alpha 属性我们可以直接拿到了,这将省掉很多类型处理上的麻烦。

然后给 UIView 添加这个 Protocol 即可:

构建一个实现了 JSExport 的 Protocol:

如用class_addProtocol对已有类导出属性

实现 JSExport 来导出已有类的属性

本质上是直接给 JS 环境增加函数,直接调用 Native 的代码

4.4 JSExportAs

一个宏,用于把OC风格的函数起一个JS风格的别名,原生仍用OC风格即每个参数都显示参数名,JS用JS风格

缺点:不灵活,不利于接口参数增减,不便于回调处理

JSExportAs(show, - (void)showMessage:(NSString *)message subtitle:(NSString *)subtitle);
- (void)show:(JSValue *)arguments {
    NSString *message = [arguments[@"message"] toString];
    NSString *subtitle = [arguments[@"subtitle"] toString];
    JSValue *handler = arguments[@"handler"];
}
show({
  message: "hello",
  subtitle: "world",
  handler: function() {
  }
})

JS运行的虚拟机,有独立的堆空间和垃圾回收机制。

4.6 JSVirtualMachine

JS和OC对象的内存管理辅助对象。由于JS内存管理是垃圾回收,并且JS中的对象都是强引用,而OC是引用计数。如果双方相互引用,势必会造成循环引用,而导致内存泄露。我们可以用JSManagedValue保存JSValue来避免。

4.5 JSManagedValue

在 JS 端调用时:

缺点举例:实现一个 HTTP 接口,参数可以非常多变,今天有可能 5 个参数明天有可能支持 6 个,在这样的假定下,我会把所有的参数传递都通过 Dictionary 来完成,比如这样:

JS代码里调用变成 show(message, subtitle);

参考文章地址如下:

是什么 javascriptcorehttps://www.kmw.com/index.php/news/3215966.html

JavaScriptCore 整体介绍https://zhuanlan.zhihu.com/p/29663994

深入浅出JavaScriptCorehttps://zhuanlan.zhihu.com/p/81634837

JavaScriptCore全面解析(上下篇)https://cloud.tencent.com/developer/article/1004875

JavaScriptCore 使用https://www.jianshu.com/p/a329cd4a67ee

iOS-JavaScriptCorehttps://www.jianshu.com/p/36412882f81d

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值