JSPatch雖然已經被蘋果明令ban掉了,但是其本身的機制對于大家理解跨平臺開發還是有很大的幫助的,bang大神雖然自己也寫過原理詳解,但是對于我等小白來說還是有點難懂其具體原理,所以自己下功夫研究了很久js和這個框架寫一篇解析給自己留做備忘也給和我一樣在路上的iOS小白們提供一些參考,本篇僅是把大家以后可能遇到的問題先解決一下
JSPatch的實現基礎是iOS的運行時機制,所有的類和變量都可以在運行時動態添加,JSPatch做的工作就是通過js和oc的交互然后動態的為運行時添加類和方法,具體請自行查找運行時的相關資料
JSPatch主要用到了一個叫JavascriptCore的庫,這個庫是webkit的一個重要組成部分,主要是對JS進行解析和提供執行環境,以下引用一下JamesYu的文章,寫的很清楚http://www.lxweimin.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代碼變成構建類所需的參數,及方法轉發的,有什么理解的不到位的地方還請大家多多指教