程序员iOS Developer

JSPatch原理解析(基础篇)

2017-08-02  本文已影响56人  Cc极生

JSPatch虽然已经被苹果明令ban掉了,但是其本身的机制对于大家理解跨平台开发还是有很大的帮助的,bang大神虽然自己也写过原理详解,但是对于我等小白来说还是有点难懂其具体原理,所以自己下功夫研究了很久js和这个框架写一篇解析给自己留做备忘也给和我一样在路上的iOS小白们提供一些参考,本篇仅是把大家以后可能遇到的问题先解决一下

JSPatch的实现基础是iOS的运行时机制,所有的类和变量都可以在运行时动态添加,JSPatch做的工作就是通过js和oc的交互然后动态的为运行时添加类和方法,具体请自行查找运行时的相关资料

JSPatch主要用到了一个叫JavascriptCore的库,这个库是webkit的一个重要组成部分,主要是对JS进行解析和提供执行环境,以下引用一下JamesYu的文章,写的很清楚http://www.jianshu.com/p/a329cd4a67ee
拿JSPatch中的代码举例如下

//OC 在context中注册一个叫_OC_callI的方法,方法实现就是等号后面的block
    context[@"_OC_callI"] = ^id(JSValue *obj, NSString *selectorName, JSValue *arguments, BOOL isSuper) {
        return callSelector(nil, selectorName, arguments, obj, isSuper);
    };
//在js中调用该方法
 var ret = instance ? _OC_callI(instance, selectorName, args, isSuper):
                         _OC_callC(clsName, selectorName, args)
//在JS中写一个方法
  var _formatOCToJS = function(obj) {
    if (obj === undefined || obj === null) return false
    if (typeof obj == "object") {...
//在OC中调用js的方法
return [[JSContext currentContext][@"_formatOCToJS"] callWithArguments:@[formatOCToJS([JPBoxing boxWeakObj:obj])]];

而且JSPatch中的所有带OC的方法都是js调用的oc的方法
另一个对于刚开始看JSPatch的iOSer来说比较难得点是js的一些问题,虽然我原来也接过前端外包写过页面,但是看到这个代码还是有很多疑惑的,比如在jspatch.js里面的代码是这样的

var global = this
;(function() {
...
}()

1.上述代码有什么作用?
function(){}是一个匿名函数,而(function() {})()可以把匿名函数封装成表达式并自我执行
首先用闭包是为了避免全局变量污染,比如如果在一个js文件里面定义了一个a变量,之后又引入一个js文件里面也定义了一个a变量,这样就会把第一个文件里面的变量覆盖掉,使用闭包就不会出现这种问题了,闭包后加一个()就可以直接执行代码这个大家应该都知道
2.为什么要有一个分号在闭包头?
匿名函数附近使用括号或一些一元运算符的惯用法,就是来引导解析器,指明运算符附近是一个表达式。但是;开头的并不常用加分号是为了避免被用做函数执行或下标运算
3.那个global = this有什么用?
将上下文this赋值给global,就可以在下之后的匿名函数中把全局变量绑定到global上方便调用

var _customMethods = {
_c: function(methodName) {...}
super: function() {...}
}

4.上述代码是什么?
在js中用下图这样的键值对形式定义一个对象,上述代码其实就是一个对象,键对应的值是一个匿名函数

var person={
firstname : "Bill",
lastname  : "Gates",
id        :  5566
};

5.JSPatch源码中用到的js的apply方法和call方法是什么?
这里有详解http://uule.iteye.com/blog/1158829
6.js里的arguments是什么?
arguments是一个特殊的js对象,可以获取传入的参数,哪怕你没有显示的声明需要传入的参数,例如

function test() {
  alert(arguments.length);//显示2
}
test(1,2)

7.Array.prototype.slice.call()有什么用?
该方法课可以将包含长度的js对象转变成数组例如

var a={length:2,0:'zero',1:'one'};
b = Array.prototype.slice.call(a);//b = ['zero','one']

8.js中的this定义
js中的this和oc中的self有很大的不同,oc中的self一直会指代的是本类本对象,即使在变量的set,get方法中也不例外,但是js中的this则指代的是最近的本对象,比如在set,get中使用this指代的是调用set和get的对象

之后几篇会按照JSPatch提供的demo代码进行一步一步讲解JSPatch的运行流程,日后有什么想到的难点我会更新在这里,之后的文章也不会对运行时如何创建类添加方法进行赘述,主要讲解JSPatch是如何将js代码变成构建类所需的参数,及方法转发的,有什么理解的不到位的地方还请大家多多指教

上一篇下一篇

猜你喜欢

热点阅读