Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 色女人综合网,国产亚洲精品美女2020久久,亚洲综合第一区

          整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          Openresrt最佳案例 - 第2篇:Lua入門

          Openresrt最佳案例 - 第2篇:Lua入門

          ua 是一種輕量小巧的腳本語言,用標(biāo)準(zhǔn)C語言編寫并以源代碼形式開放, 其設(shè)計(jì)目的是為了嵌入應(yīng)用程序中,從而為應(yīng)用程序提供靈活的擴(kuò)展和定制功能。

          Lua 是巴西里約熱內(nèi)盧天主教大學(xué)(Pontifical Catholic University of Rio de Janeiro)里的一個(gè)研究小組,由Roberto Ierusalimschy、Waldemar Celes 和 Luiz Henrique de Figueiredo所組成并于1993年開發(fā)。 —摘抄 http://www.runoob.com/lua/lua-tutorial.html

          環(huán)境搭建

          注意: 在上一篇文章中,OpenResty已經(jīng)有了Lua的環(huán)境,這里安裝的是單獨(dú)的Lua環(huán)境,用于學(xué)習(xí)和開發(fā)Lua。大多數(shù)的電腦是Windowds版本的電腦,Windows版本下載地址http://luaforge.net/projects/luaforwindows/。

          Linux和Mac電腦下載地址:http://luajit.org/download.html,安裝命令如下:

          wget http://luajit.org/download/LuaJIT-2.1.0-beta1.tar.gz
          tar -xvf LuaJIT-2.1.0-beta1.tar.gz
          cd LuaJIT-2.1.0-beta1
          make
          sudo make install
          

          使用IDEA開發(fā)的同學(xué),可以通過安裝插件的形式來集成Lua的環(huán)境,插件名為EmmyLua,安裝插件后,在Idea的右側(cè)欄就會(huì)出現(xiàn)Lua的圖標(biāo),點(diǎn)擊圖標(biāo),就會(huì)出現(xiàn)運(yùn)行Lua代碼的窗口。建議使用該插件,可以免去安裝Lua環(huán)境的麻煩。

          第一個(gè)Lua程序

          安裝好環(huán)境后,我采用EmmyLua插件的形式,對(duì)Lua的入門語法進(jìn)行一個(gè)簡(jiǎn)單的講解。 打開EmmyLua的終端,在終端上輸入:

          print("hi you")
          

          按ctrl+enter,終端顯示:

          hi you

          Lua基本數(shù)據(jù)類型

          lua的基本數(shù)據(jù)類型有nil、string、boolean、number、function類型。

          nil 類型

          nil類似于Java中的null ,表示空值。變量第一次賦值為nil。

          local num

          print(num)

          num=100

          print(num)

          終端輸出:

          nil

          100

          number (數(shù)字)

          Number 類型用于表示實(shí)數(shù),和 Java里面的 double 類型很類似。可以使用數(shù)學(xué)函數(shù) math.floor(向下取整) 和 math.ceil(向上取整) 進(jìn)行取整操作。

          local order=3.99
          local score=98.01
          print(math.floor(order))
          print(math.ceil(score))
          

          輸出:

          3

          99

          string 字符串

          Lua 中有三種方式表示字符串: 1、使用一對(duì)匹配的單引號(hào)。例:’hello’。 2、使用一對(duì)匹配的雙引號(hào)。例:”abclua 3.字符串還可以用一種長(zhǎng)括號(hào)(即[[ ]]) 括起來的方式定義

          ocal str1='hello world'

          local str2="hello lua"

          local str3=[["add\name",'hello']]

          local str4=[=[string have a [[]].]=]

          print(str1) -->output:hello world

          print(str2) -->output:hello lua

          print(str3) -->output:"add\name",'hello'

          print(str4) --

          table (表)

          Table 類型實(shí)現(xiàn)了一種抽象的“關(guān)聯(lián)數(shù)組”。“關(guān)聯(lián)數(shù)組”是一種具有特殊索引方式的數(shù)組,索引通常是字符串(string) 或者 number 類型,但也可以是除 nil 以外的任意類型的值。

          local corp={
           web="www.google.com", --索引為字符串,key="web",
           -- value="www.google.com"
           telephone="12345678", --索引為字符串
           staff={"Jack", "Scott", "Gary"}, --索引為字符串,值也是一個(gè)表
           100876, --相當(dāng)于 [1]=100876,此時(shí)索引為數(shù)字
           -- key=1, value=100876
           100191, --相當(dāng)于 [2]=100191,此時(shí)索引為數(shù)字
           [10]=360, --直接把數(shù)字索引給出
           ["city"]="Beijing" --索引為字符串
          }
          print(corp.web) -->output:www.google.com
          print(corp["telephone"]) -->output:12345678
          print(corp[2]) -->output:100191
          print(corp["city"]) -->output:"Beijing"
          print(corp.staff[1]) -->output:Jack
          print(corp[10]) -->output:36
          

          function(函數(shù))

          在 Lua 中,函數(shù) 也是一種數(shù)據(jù)類型,函數(shù)可以存儲(chǔ)在變量中,可以通過參數(shù)傳遞給其他函 數(shù),還可以作為其他函數(shù)的返回值。

          local function foo()
           print("in the function")
           --dosomething()
           local x=10
           local y=20
           return x + y
          end
          local a=foo --把函數(shù)賦給變量
          print(a())
          --output:
          in the function
          30
          

          表達(dá)式

          ~=不等于

          邏輯運(yùn)算符說明and邏輯與or邏輯或not邏輯非

          • a and b 如果 a 為 nil,則返回 a,否則返回 b;
          • a or b 如果 a 為 nil,則返回 b,否則返回 a。

          local c=nil

          local d=0

          local e=100

          print(c and d) -->打印 nil

          print(c and e) -->打印 nil

          print(d and e) -->打印 100

          print(c or d) -->打印 0

          print(c or e) -->打印 100

          print(not c) -->打印 true

          print(not d) --> 打印 false

          在 Lua 中連接兩個(gè)字符串,可以使用操作符“..”(兩個(gè)點(diǎn)).

          print("Hello " .. "World") -->打印 Hello World
          print(0 .. 1) -->打印 01
          

          控制語句

          單個(gè) if 分支 型

          x=10
          if x > 0 then
           print("x is a positive number")
          end
          

          兩個(gè)分支 if-else 型

          x=10
          if x > 0 then
           print("x is a positive number")
          else
           print("x is a non-positive number")
          end
          

          多個(gè)分支 if-elseif-else 型:

          score=90
          if score==100 then
           print("Very good!Your score is 100")
          elseif score >=60 then
           print("Congratulations, you have passed it,your score greater or equal to 60")
           --此處可以添加多個(gè)elseif
          else
           print("Sorry, you do not pass the exam! ")
          end
          

          for 控制結(jié)構(gòu)

          Lua 提供了一組傳統(tǒng)的、小巧的控制結(jié)構(gòu),包括用于條件判斷的 if 用于迭代的 while、repeat 和 for,本章節(jié)主要介紹 for 的使用.

          for 數(shù)字型

          for 語句有兩種形式:數(shù)字 for(numeric for) 和范型 for(generic for) 。 數(shù)字型 for 的語法如下:

          for var=begin, finish, step do

          --body

          end

          實(shí)例1:

          for i=1, 5 do
           print(i)
          end
          -- output:
          1 2 3 4 5
          

          實(shí)例2:

          for i=1, 10, 2 do

          print(i)

          end

          -- output:

          1 3 5 7 9

          for 泛型

          泛型 for 循環(huán)通過一個(gè)迭代器(iterator) 函數(shù)來遍歷所有值:

          -- 打印數(shù)組a的所有值
          local a={"a", "b", "c", "d"}
          for i, v in ipairs(a) do
           print("index:", i, " value:", v)
          end
          -- output:
          index: 1 value: a
          index: 2 value: b
          index: 3 value: c
          index: 4 value: d
          

          lua的入門就到這里,因?yàn)閘ua語法雖少,但細(xì)節(jié)有很多,不可能花很多時(shí)間去研究這個(gè)。入個(gè)門,遇到問題再去查資料就行了。另外需要說明的是本文大部分內(nèi)容為復(fù)制粘貼于OPenResty 最佳實(shí)踐,感謝原作者的開源電子書,讓我獲益匪淺。更多內(nèi)容請(qǐng)參考:

          lua入門教程:http://www.runoob.com/lua/lua-tutorial.html

          OPenResty 最佳實(shí)踐: https://moonbingbing.gitbooks.io/openresty-best-practices/content/index.html

          年來,前端技術(shù)日新月異,前端已經(jīng)不僅僅是網(wǎng)頁,更多的開始由狹義向廣義發(fā)展。

          先后涌現(xiàn)出了具備后端能力的node,具備移動(dòng)開發(fā)能力的react native,具備游戲渲染能力的cocos2d-js,以及iOS上的熱修復(fù)技術(shù)JSPatch等等新技術(shù)。

          咋一看,幾乎各個(gè)端都被JavaScript攻陷,大有一統(tǒng)江湖之勢(shì)。

          究竟,JavaScript如何做到上天入地?zé)o所不能?JavaScript真的能一統(tǒng)江湖嗎?

          亂世出英雄:JavaScript的誕生故事要從JavaScript的由來說起。

          高能瞎扯淡版,正經(jīng)臉的同學(xué)可以忽略

          有人的地方就有江湖,有江湖的地方就有紛爭(zhēng)。

          故事要從當(dāng)年的瀏覽器之戰(zhàn)說起。

          時(shí)間回到1994年,

          (→ 那時(shí)候我還是個(gè)寶寶~ #天真臉#)

          景兄弟橫空出世,并自帶神器網(wǎng)景導(dǎo)航,戰(zhàn)斗力爆表,勢(shì)如劈竹,瞬時(shí)間威震天下。

          一出世就武裝到牙齒,武力值這么高還自帶兵器,這個(gè)科學(xué)嗎?

          港真,我也覺得不科學(xué),也許跟熊孩子哪吒、女漢子雅典娜是一個(gè)品種吧?

          這一切北方的老前輩微軟大濕,都看在眼里,不甘天下盡歸景兄弟這個(gè)初出茅廬的毛孩子,大濕積淀多年,潛心修煉一年,終于帶著大殺器IE 1.0出關(guān)了,誓于景兄弟爭(zhēng)個(gè)高低。

          自此景兄弟的網(wǎng)景導(dǎo)航 VS 微軟大濕的IE 的軍備戰(zhàn)爭(zhēng)開始。

          景兄弟仔細(xì)掂量,微軟大濕財(cái)大氣粗,內(nèi)功深厚,臣妾實(shí)在是辦不到啊啊啊啊啊啊。

          景兄弟緊急召集門人商議對(duì)策,有一門人曰:”以我們微薄之力硬磕,是萬萬使不得的。如今我們,一是宜施行合縱之策,抱大腿,組成聯(lián)盟!二是避其鋒芒,出奇招致勝。“

          于是景兄弟依照此策略,一方面找到了當(dāng)時(shí)德高為重的另一位前輩SUN,組成了開發(fā)者聯(lián)盟。

          (微軟大濕:握草,聯(lián)盟都粗來了,那我是不是得搞個(gè)部落?)

          另一方面,景兄弟找到了鍛造大師布蘭登,請(qǐng)布大師幫忙升級(jí)兵器網(wǎng)景導(dǎo)航,大師就是大師,不費(fèi)吹灰之力就完成了強(qiáng)化升級(jí),然而布大師突發(fā)奇想,本來這是近距離攻擊兵器,要是有多一個(gè)遠(yuǎn)距離攻擊的能力那豈不是更好?Just do it. 想罷大師就加了一個(gè)遠(yuǎn)距離攻擊的feature。于是有了自帶遠(yuǎn)距離攻擊能力的網(wǎng)景導(dǎo)航2.0。景兄弟一看這么流弊心里甚是歡喜,不過遠(yuǎn)距離攻擊的技能叫做LiveScript,感覺不是特別Fashion。特然想到這不是跟SUN前輩聯(lián)盟嘛,SUN家的Java正是獨(dú)霸武林之時(shí)。不如把名字改成跟Java有關(guān),蹭一把東風(fēng),蹭點(diǎn)光環(huán)。一拍腦袋,JavaScript!!!眾門人一聽:”好好好,JavaScript 流弊炫酷吊炸天!“

          果然第一節(jié)下半場(chǎng),景兄弟攜強(qiáng)化過的網(wǎng)景導(dǎo)航2.0 戰(zhàn)個(gè)痛快,那是杠杠的!人家一問,你咋還能遠(yuǎn)程攻擊,你這個(gè)遠(yuǎn)程攻擊用的是啥?答曰:JavaScript。“JavaScript,一定是跟SUN家Java是一個(gè)系列產(chǎn)品,一定很流弊!”#光環(huán)加成,各種膜拜臉#

          微軟大濕虧了一場(chǎng),痛定思痛,也要搞遠(yuǎn)程攻擊功能,果然不久,就祭出了同樣帶有遠(yuǎn)程攻擊能力的IE 3.0,鑒于景兄弟的遠(yuǎn)程攻擊叫做JavaScript,J開頭的感覺應(yīng)該比較流弊,所以微軟大濕的叫做JScript。

          然后戰(zhàn)爭(zhēng)就從地面貼身肉搏戰(zhàn),開始逐步升級(jí)到了遠(yuǎn)距離核戰(zhàn)爭(zhēng)。

          正所謂,城門失火,殃及池魚。這么打下去苦逼的是搬磚的頁面仔,就是我這種,到處都是雷區(qū),無處下腳。

          最后到了1997年,“聯(lián)合國安理會(huì)秘書長(zhǎng)”艾瑪(ECMA)出來調(diào)停,多方簽署了“核不擴(kuò)散條約”,約束各種遠(yuǎn)程攻擊武器的使用,這才走上了正軌。

          1995年SUN開發(fā)了Java技術(shù),這是第一個(gè)通用軟件平臺(tái)。Java擁有跨平臺(tái)、面向?qū)ο蟆⒎盒途幊痰奶匦裕瑥V泛應(yīng)用于企業(yè)級(jí)Web應(yīng)用開發(fā)和移動(dòng)應(yīng)用開發(fā)。Java也伴隨著互聯(lián)網(wǎng)的迅猛發(fā)展而發(fā)展,逐漸成為重要的網(wǎng)絡(luò)編程語言。名噪一時(shí)。

          1994年Netscape公司成立,并推出了自己的瀏覽器的免費(fèi)版本 Netscape Navigator,很快就占有了瀏覽器市場(chǎng)。到了 1995 年,微軟公司開始加入,并很快發(fā)布了自己的 Internet Explorer 1.0。

          1995年,當(dāng)時(shí)在Netscape就職的Brendan Eich(布蘭登·艾克),正為Netscape Navigator 2.0瀏覽器開發(fā)的一門名為L(zhǎng)iveScript的腳本語言,后來Netscape與Sun Microsystems組成的開發(fā)聯(lián)盟,為了讓這門語言搭上Java這個(gè)編程語言“熱詞”,將其臨時(shí)改名為“JavaScript”,日后這成為大眾對(duì)這門語言有諸多誤解的原因之一。

          JavaScript最初受Java啟發(fā)而開始設(shè)計(jì)的,目的之一就是“看上去像Java”,因此語法上有類似之處,一些名稱和命名規(guī)范也借自Java。但JavaScript的主要設(shè)計(jì)原則源自Self和Scheme。JavaScript與Java名稱上的近似,是當(dāng)時(shí)Netscape為了營銷考慮與SUN達(dá)成協(xié)議的結(jié)果。

          ==> 所以,JavaScript和Java其實(shí)沒有半毛錢關(guān)系。

          JavaScript推出后在瀏覽器上大獲成功,微軟在不久后就為Internet Explorer 3.0瀏覽器推出了JScript,以與處于市場(chǎng)領(lǐng)導(dǎo)地位的Netscape產(chǎn)品同臺(tái)競(jìng)爭(zhēng)。JScript也是一種JavaScript實(shí)現(xiàn),這兩個(gè)

          JavaScript語言版本在瀏覽器端共存意味著語言標(biāo)準(zhǔn)化的缺失,對(duì)這門語言進(jìn)行標(biāo)準(zhǔn)化被提上了日程,在1997年,由Netscape、SUN、微軟、寶藍(lán)等公司組織及個(gè)人組成的技術(shù)委員會(huì)在ECMA(歐洲計(jì)算機(jī)制造商協(xié)會(huì))確定定義了一種名叫ECMAScript的新腳本語言標(biāo)準(zhǔn),規(guī)范名為ECMA-262。JavaScript成為了ECMAScript的實(shí)現(xiàn)之一。ECMA-262 第五版,即是ES5。

          ==> ECMA-262,包括ES5, ES6等是一個(gè)標(biāo)準(zhǔn),JavaScript是ECMAScript的一個(gè)實(shí)現(xiàn)。

          完整的JavaScript實(shí)現(xiàn)應(yīng)該包含三個(gè)部分:

          在網(wǎng)景導(dǎo)航2.0和IE 3.0出現(xiàn)之后的幾年間,網(wǎng)景和微軟公司不停的發(fā)布新版本的瀏覽器,支持更多的新功能。自此拉開了瀏覽器之戰(zhàn)的序幕。這場(chǎng)瀏覽器之戰(zhàn)到現(xiàn)在還在繼續(xù),以下一張圖看清楚過程。

          從瀏覽器之戰(zhàn)可以看出,各家瀏覽器比拼的大致兩個(gè)方面視覺體驗(yàn)(渲染排版)和速度(腳本運(yùn)行)。

          ==> 所以一個(gè)完整的瀏覽器組成,至少包含兩個(gè)部分:

          補(bǔ)充一個(gè)市面常見瀏覽器的內(nèi)核和JavaScript引擎搭配:

          其他JavaScript引擎,Rhino,由Mozilla基金會(huì)管理,開放源代碼,完全以Java編寫,可以看做SpiderMonkey的Java版。

          注意:webkit不單單只是一個(gè)排版引擎,webkit=排版引擎 + JavaScript引擎。

          ==> 所以,JavaScript是動(dòng)態(tài)語言,它的運(yùn)行都是基于JavaScript引擎,引擎大都是由靜態(tài)語言實(shí)現(xiàn)C++、Java、and so on。JavaScript的能力也是由引擎賦予。不管是瀏覽器環(huán)境中是window,亦或是node環(huán)境中的process,均是由引擎提供。

          (番外:Mozilla的人不知道為啥特別喜歡猴子,經(jīng)常以猴子命名技術(shù),所以看到帶Monkey的,十有八九估計(jì)是他們搞的。)

          諾曼底登陸:JavaScript Binding/Bridge 橋接技術(shù)

          在瀏覽器環(huán)境中,DOM、BOM、window對(duì)象、setTimeout/setInterval,alert,console等方法均不是JavaScript自身具備的能力,而是瀏覽器native實(shí)現(xiàn),然后通過JavaScript引擎注入到JS運(yùn)行的全局上下文中,供JS使用。

          鑒別方式,在調(diào)試器console中打出來,帶有[native code]的即是:

          講道理:

          1. JavaScript運(yùn)行 → 依賴于JavaScript引擎 ← 瀏覽器集成了JavaScript引擎,同時(shí)通過JavaScript引擎注入native代碼工JS腳本使用

          2. 發(fā)散一下思維,只要有JavaScript引擎,就能運(yùn)行JS腳本,不管有沒有瀏覽器!只是缺少瀏覽器提供的alert,window等方法。

          3. 既然瀏覽器可以往JavaScript引擎中注入代碼,賦予JS腳本在網(wǎng)頁中特殊的能力,同理我們可以自己集成JavaScript引擎,自己定義自己的方法往JavaScript引擎中注入,賦予JS更多更強(qiáng)的自定義能力!

            注入的關(guān)鍵是:值類型相互對(duì)應(yīng),Obj映射class的一個(gè)實(shí)例,function映射一個(gè)句柄或者引用

          JavaScript數(shù)值型中的坑

          JavaScript內(nèi)部,所有數(shù)字都是以64位浮點(diǎn)數(shù)形式儲(chǔ)存,即使整數(shù)也是如此

          這就是說,在JavaScript語言的底層,根本沒有整數(shù),所有數(shù)字都是小數(shù)(64位浮點(diǎn)數(shù))。容易造成混淆的是,某些運(yùn)算只有整數(shù)才能完成,此時(shí)JavaScript會(huì)自動(dòng)把64位浮點(diǎn)數(shù),轉(zhuǎn)成32位整數(shù),然后再進(jìn)行運(yùn)算。由于浮點(diǎn)數(shù)不是精確的值,所以涉及小數(shù)的比較和運(yùn)算要特別小心。盡量避免使用JavaScript做精準(zhǔn)計(jì)算和密集計(jì)算。

          根據(jù)國際標(biāo)準(zhǔn)IEEE 754,JavaScript浮點(diǎn)數(shù)的64個(gè)二進(jìn)制位,從最左邊開始,是這樣組成的。

          • 第1位:符號(hào)位,0表示正數(shù),1表示負(fù)數(shù)

          • 第2位到第12位:儲(chǔ)存指數(shù)部分

          • 第13位到第64位:儲(chǔ)存小數(shù)部分(即有效數(shù)字)

            符號(hào)位決定了一個(gè)數(shù)的正負(fù),指數(shù)部分決定了數(shù)值的大小,小數(shù)部分決定了數(shù)值的精度。

            IEEE 754規(guī)定,有效數(shù)字第一位默認(rèn)總是1,不保存在64位浮點(diǎn)數(shù)之中。也就是說,有效數(shù)字總是1.xx…xx的形式,其中xx..xx的部分保存在64位浮點(diǎn)數(shù)之中,最長(zhǎng)可能為52位。因此,JavaScript提供的有效數(shù)字最長(zhǎng)為53個(gè)二進(jìn)制位(64位浮點(diǎn)的后52位+有效數(shù)字第一位的1)。

          內(nèi)部表現(xiàn)公式:(-1)^符號(hào)位 1.xx…xx 2^指數(shù)位

          精度最多只能到53個(gè)二進(jìn)制位,這意味著,絕對(duì)值小于2的53次方的整數(shù),即-(253-1)到253-1,都可以精確表示。

          而大部分的后端語言,C++、Java、Python等的long型都是可以支持到64位,因此long型數(shù)據(jù)從后端語言傳給JavaScript會(huì)發(fā)生低位截?cái)?/strong>。遇到這種情況一般使用String處理,如需要在JavaScript中做long型計(jì)算,需要自行實(shí)現(xiàn)計(jì)算器。

          有了自行往JavaScript引擎中注入的想法,接下來就是分析可行性。

          大部分是JavaScript引擎是使用C++編寫,如果自己的程序使用的是C++可以很方便的進(jìn)行注入,如果是OC,可以使用OC和C++混編的形式。

          其他語言怎么破?

          要在一門靜態(tài)語言上與動(dòng)態(tài)語言JavaScript相互調(diào)用,最便捷的方式是找到一個(gè)這門語言實(shí)現(xiàn)的JavaScript引擎(開源),直接進(jìn)行集成,注入。如果沒有,則需要使用多一層橋接,把這門語言的接口暴露給C++,再由C++實(shí)現(xiàn)的JavaScript引擎將接口注入供JavaScript使用。

          服務(wù)端集成思路&實(shí)踐:

          nodeJS中的橋接

          我們都知道nodeJS,但是nodeJS的運(yùn)行依賴于Google的V8 引擎,V8是C++實(shí)現(xiàn),底層使用C++實(shí)現(xiàn)底層功能,比如網(wǎng)絡(luò),數(shù)據(jù)庫IO,對(duì)外暴露一個(gè)構(gòu)造器接口注入到上下文中,注意此處暴露的只是一個(gè)構(gòu)造器接口而不是一個(gè)創(chuàng)建完的實(shí)例。然后實(shí)現(xiàn)了一個(gè)require的hook函數(shù)。當(dāng)使用require加載一個(gè)JS模塊時(shí),跟網(wǎng)頁中使用AMD 的require并無異樣,當(dāng)使用require加載系統(tǒng)庫,既是C++的模塊時(shí),會(huì)調(diào)用暴露出來的構(gòu)造器接口,得到一個(gè)實(shí)例對(duì)象。不管是裝載JS模塊還是裝載C++模塊,得到的都可以看做是一個(gè)Module Object,node會(huì)將裝載完的模塊緩存到binding_cache中,下次在別處的代碼中使用require裝載模塊時(shí),就會(huì)先去binding_cache中查找,如果找到了則返回該module object,如果沒找到再執(zhí)行上面的裝載流程。

          這就是node的基本原理:C++封裝底層操作,通過V8注入,使得JS腳本有網(wǎng)絡(luò)和IO能力

          基于Spring的橋接

          以上說到的幾個(gè)都是C++層面的應(yīng)用,那么經(jīng)典的Java怎么玩?是不是Java就必須是靜態(tài)語言的玩法,沒有辦法像C++之類的,可以使用JS的動(dòng)態(tài)特性?

          當(dāng)然不是。這個(gè)時(shí)候,我們需要說起前面介紹過的一個(gè)JS引擎 Rhino,Rhino是完全由Java編寫,可想而知,Rhino幾乎就是為Java應(yīng)用而生的。

          用法是這樣:

          1. 首先在我們的Java應(yīng)用中集成Rhino;

          2. 所有的IO操作,網(wǎng)絡(luò)操作等,都封裝成service,并提供增刪改查,setter && getter等多種方法

          3. 通過spring,把這些service bean注入到Rhino中;

          4. 把業(yè)務(wù)邏輯寫到JS代碼中,JS代碼調(diào)用多個(gè)已注入的Java service處理業(yè)務(wù)邏輯,拼裝數(shù)據(jù)返回!

          好處:修改業(yè)務(wù)邏輯不需要修改Java代碼,也就是不需要重新編譯和部署,只需要刷新下跑在Rhino中的JS代碼即可。以往Java應(yīng)用的一個(gè)痛點(diǎn)是部署,需要重新編譯,打包,部署重啟服務(wù)器,現(xiàn)在以這種形式開發(fā),可以達(dá)到服務(wù)端的熱更新和熱部署。既可以享有Java服務(wù)的穩(wěn)定性和可靠性,又可以享有JS的靈活性。

          這種技術(shù)和用法在差不多十年前就有過,前EMC的工程師基于EMC著名的商業(yè)產(chǎn)品Documentum,設(shè)計(jì)了一套Java開源的中小企業(yè)CMS系統(tǒng)Alfresco,在該系統(tǒng)中實(shí)現(xiàn)了這種技術(shù),這種技術(shù)基于spring,叫做spring-surf,做了一個(gè)膠水層。可以看做小十年前的node吧。

          Demo,使用spring-surf框架的系統(tǒng)中一個(gè)webscript模塊

          1. categorynode.get.xml定義URL攔截器和權(quán)限控制;

          2. .get指明是處理GET請(qǐng)求,RESTful;

          3. 在categorynode.get.js中調(diào)用已注入的Java Bean處理業(yè)務(wù)邏輯;

          4. 若為網(wǎng)頁請(qǐng)求返回.html.ftl,若為Ajax,返回.json.ftl;

          (此處配套使用的是FreeMarker模板引擎)

          ==> categorynode.get.desc.xml

          ==> categorynode.get.js

          ==> categorynode.get.html.ftl

          ==> categorynode.get.json.ftl

          移動(dòng)端集成思路&實(shí)踐:

          React Native中的橋接

          React Native目前也是異常火爆,RN程序的運(yùn)行依賴于Facebook的RN框架。在iOS、Android的模擬器或是真機(jī)上,React Native使用的是JavaScriptCore引擎,也就是Safari所使用的JavaScript引擎。但是在iOS上JavaScriptCore并沒有使用即時(shí)編譯技術(shù)(JIT),因?yàn)樵趇OS中應(yīng)用無權(quán)擁有可寫可執(zhí)行的內(nèi)存頁(因而無法動(dòng)態(tài)生成代碼),在安卓上,理論上是可以使用的。JavaScriptCore引擎也是使用C++編寫,在iOS和安卓中,JavaScriptCore都做了一層封裝,可以無須關(guān)心引擎和系統(tǒng)橋接的那一層。iOS/Android系統(tǒng)通過JavaScriptCore引擎將定制好的各種原生組件注入,如:listview,text等。

          Cocos2d-JS中的橋接

          cocos2dx是游戲開發(fā)中非常常用的游戲渲染引擎,有一系列的產(chǎn)品,如:cocos2dx(C++),cocos2d-lua(lua), cocos2d-js(JavaScript)等多個(gè)產(chǎn)品。其中最新退出的是cocos2dx的JS版本的cocos2d-js,編寫游戲渲染特效代碼相比于C++和lua非常方便。對(duì)于做需要經(jīng)常更新的渲染場(chǎng)景,C++是靜態(tài)語言,每次修改都需要重新編譯才能運(yùn)行,顯然是不合適的。自然也就想到了腳本語言,lua和js,兩者有些類似,都是動(dòng)態(tài)語言,只需要集成一個(gè)運(yùn)行引擎,提供一個(gè)運(yùn)行的容器即可運(yùn)行,同時(shí)通過引擎注入底層方法供腳本調(diào)用即可。lua好處是精簡(jiǎn),語法精簡(jiǎn),引擎頁很小很精簡(jiǎn),所以不可避免的代碼量會(huì)比js多,同時(shí)學(xué)習(xí)成本比較高。js的好處是有ECMAScrtpt的核心,語法比較豐富,同時(shí)有支持一些高級(jí)屬性。在cocos2d-js中,cocos2dx(C++)集成了SpiderMonkey(C++)作為JS運(yùn)行引擎,中間做了一個(gè)膠水層既是JS Binding,通過引擎注入了一個(gè)cc的全局對(duì)象,映射的是底層C++的一個(gè)單例C++實(shí)例。表面上寫的是JS代碼,實(shí)際上操作的是底層的C++。cocos2d-js是代碼可以運(yùn)行在多種環(huán)境中,當(dāng)運(yùn)行的網(wǎng)頁環(huán)境中時(shí),使用的是cocos2d-html5引擎,底層操作的是canvas;當(dāng)運(yùn)行在客戶端上時(shí),使用的是cocos2dx引擎,底層操作的是C++,再由C++去操控openGL做繪制和渲染。提供相同的API,對(duì)開發(fā)者幾乎是透明無差異的,開發(fā)者只需要關(guān)注實(shí)現(xiàn)效果即可。達(dá)到一套代碼,多端運(yùn)行(網(wǎng)頁端,客戶端)。

          JSPatch技術(shù)中的橋接

          JSPatch是目前比較流行的iOS上的熱修復(fù)技術(shù),JSPatch 能做到通過 JS 調(diào)用和改寫 OC 方法最根本的原因是 Objective-C 是動(dòng)態(tài)語言,OC 上所有方法的調(diào)用/類的生成都通過 Objective-C Runtime 在運(yùn)行時(shí)進(jìn)行,我們可以通過類名/方法名反射得到相應(yīng)的類和方法。JSPatch 的基本原理就是:JS 傳遞字符串給 OC,OC 通過 Runtime 接口調(diào)用和替換 OC 方法。

          關(guān)鍵技術(shù)之一是 JS 和 OC 之間的消息互傳。JSPatch里包含了,一個(gè)JS引擎JavaScriptCore(Safari,React Native用的同款)。用到了 JavaScriptCore 的接口,OC 端在啟動(dòng) JSPatch 引擎時(shí)會(huì)創(chuàng)建一個(gè) JSContext 實(shí)例,JSContext 是 JS 代碼的執(zhí)行環(huán)境,可以給 JSContext 添加方法,JS 就可以直接調(diào)用這個(gè)方法。本質(zhì)上就是通過JavaScriptCore引擎注入,暴露OC的方法供JS調(diào)用來實(shí)現(xiàn)動(dòng)態(tài)修改OC的反射。

          Demo,iOS熱更新,熱修復(fù):

          1. 集成JavaScriptCore引擎;

          2. 通過引擎,橋接JS和OC;

          3. 通過JS修改OC反射。

          詳細(xì)的JSPatch技術(shù)介紹請(qǐng)移步:https://github.com/bang590/JSPatch/wiki

          關(guān)于JavaScript引擎:

          在iOS 或 android 上能夠運(yùn)行的JavaScript 引擎有4個(gè):JavaScriptCore,SpiderMonkey,V8,Rhino。下面這個(gè)表格展示各個(gè)引擎在iOS 和 Android 的兼容性。

          因?yàn)閕OS平臺(tái)不支持JIT即時(shí)編譯,而V8只有JIT模式,所以V8無法在iOS平臺(tái)使用(越獄設(shè)備除外,想體驗(yàn)iOS JIT的同學(xué)可以自行越獄)。

          所以,目前可以做到橫跨iOS和Android雙平臺(tái)的JS引擎,只有兩款,即是SpiderMonkey和JavaScriptCore。

          JavaScript引擎會(huì)受很多東西影響,比如交叉編譯器的版本、引擎的版本和操作系統(tǒng)的種類等。

          至于如何選擇,可以參考:《Part I: How to Choose a JavaScript Engine for iOS and Android Development》

          至此,JavaScript從立足于前端,到征戰(zhàn)全端的逆襲之路,可以總結(jié)為“攜引擎以令天下”。

          不足之處,還請(qǐng)各位看官輕拍~

          參考文章:

          bang590/JSPatch中問參考文檔

          Cocos2d-JS | Cocos2d-x官方參考文檔

          Alfresco官方參考文檔

          《Browser Wars: The End or Just the Beginning?》

          《Part I: How to Choose a JavaScript Engine for iOS and Android Development》

          《React Native 從入門到源碼》

          • 單行注釋

          兩個(gè)減號(hào)是單行注釋

          --
          
          • 多行注釋
          --[[
           多行注釋
           多行注釋
           --]]
          

          基本數(shù)據(jù)類型

          Lua 中有 8 個(gè)基本類型分別為:nilbooleannumberstringuserdatafunctionthreadtable

          nil

          • nil 類型表示一種沒有任何有效值,它只有一個(gè)值 nil
          • 給全局變量或者 table 表里的變量賦一個(gè) nil 值,等同于把它們刪掉
          • nil 作比較時(shí)應(yīng)該加上雙引號(hào) “
          > type(a)
          nil
          > type(a)==nil
          false
          > type(a)=='nil'
          true
          > type(type(a))
          string
          

          boolean

          boolean 類型只有兩個(gè)可選值:true和 false,Lua 把falsenil看作是”假”,其他的都為”真”。

          number

          Lua 默認(rèn)只有一種 number 類型 :double(雙精度)類型。

          string

          字符串由一對(duì)雙引號(hào)或單引號(hào)來表示,也可以用 2 個(gè)方括號(hào) “[[]]” 來表示”一塊”字符串

          > html=[[
          >> <html>
          >> <head></head>
          >> <body>
          >> <a >Gitlib</a>
          >> </body>
          >> </html>
          >> ]]
          > print(html)
          

          table

          • 在 Lua 里,table 的創(chuàng)建是通過”構(gòu)造表達(dá)式”來完成,最簡(jiǎn)單構(gòu)造表達(dá)式是{}。
          • Lua 中的表(table)其實(shí)是一個(gè)”關(guān)聯(lián)數(shù)組”,數(shù)組的索引可以是數(shù)字或者是字符串。
          • 不同于其他語言的數(shù)組把 0 作為數(shù)組的初始索引,在 Lua 里表的默認(rèn)初始索引一般以 1 開始

          function

          在 Lua 中,函數(shù)是被看作是一種特殊的變量,函數(shù)可以存在變量里。

          thread

          在 Lua 里,最主要的線程是協(xié)同程序(coroutine)。它跟線程(thread)差不多,擁有自己獨(dú)立的局部變量指令指針,可以跟其他協(xié)同程序共享全局變量和其他大部分東西。

          線程跟協(xié)程的區(qū)別:線程可以同時(shí)多個(gè)運(yùn)行,而協(xié)程任意時(shí)刻只能運(yùn)行一個(gè),并且處于運(yùn)行狀態(tài)的協(xié)程只有被掛起(suspend)時(shí)才會(huì)暫停。

          userdata

          userdata 是一種用戶自定義數(shù)據(jù),用于表示一種由應(yīng)用程序或 C/C++ 語言庫所創(chuàng)建的類型,可以將任意 C/C++ 的任意數(shù)據(jù)類型的數(shù)據(jù)(通常是 struct 和 指針)存儲(chǔ)到 Lua 變量中調(diào)用。

          變量

          • Lua 中的變量全是全局變量那怕是語句塊或是函數(shù)里,除非用 local 顯式聲明為局部變量。
          • 局部變量的作用域?yàn)閺穆暶魑恢瞄_始到所在語句塊結(jié)束。
          • 變量的默認(rèn)值均為 nil。
          • 多個(gè)變量可以同時(shí)賦值。
          • ?
          > function joke()
          >> c=5 -- 全局變量
          >> local d=6 -- 局部變量
          >> end
          > 
          > joke()
          > print(c,d) 
          -- 輸出結(jié)果,在函數(shù)中定義的變量依然是全局變量
          5	nil
          -- 多個(gè)變量賦值
          > a, b, c=0, 1
          > print(a,b,c) 
          0	1	nil
          

          循環(huán)語句

          注意:Lua僅支持break跳出循環(huán),不支持continue;

          • while循環(huán)
          while(condition)
          do
           statements
          end
          
          • for循環(huán)
          -- 數(shù)值
          for var=min,max,step do 
           statements
          end 
          -- table進(jìn)行for循環(huán),ipairs為迭代器方法
          a={"one", "two", "three"}
          for i, v in ipairs(a) do
           print(i, v)
          end
          
          • repeat循環(huán)
          repeat
           statements
          until( condition
          

          條件語句

          if( 布爾表達(dá)式 1)
          then
           --[ 在布爾表達(dá)式 1 為 true 時(shí)執(zhí)行該語句塊 --]
          elseif( 布爾表達(dá)式 2)
          then
           --[ 在布爾表達(dá)式 2 為 true 時(shí)執(zhí)行該語句塊 --]
          else 
           --[ 如果以上布爾表達(dá)式都不為 true 則執(zhí)行該語句塊 --]
          end
          

          函數(shù)

          • Lua函數(shù)可以返回多個(gè)結(jié)果值;
          • Lua函數(shù)可以接受可變數(shù)目的參數(shù),和 C 語言類似,在函數(shù)參數(shù)列表中使用三點(diǎn)...表示函數(shù)有可變的參數(shù),通過select("#",...)來獲取可變參數(shù)的數(shù)量;
          function add(...) 
          local s=0 
           for i, v in ipairs{...} do -- {...} 表示一個(gè)由所有變長(zhǎng)參數(shù)構(gòu)成的數(shù)組 
           s=s + v 
           end 
           return s 
          end
          

          字符串操作

          表操作

          模塊與包

          • Lua的模塊是由變量、函數(shù)等已知元素組成的table;
          • 創(chuàng)建一個(gè)模塊很簡(jiǎn)單,就是創(chuàng)建一個(gè) table,然后把需要導(dǎo)出的常量、函數(shù)放入其中,最后返回這個(gè) table 就行;
          -- 文件名為 module.lua
          -- 定義一個(gè)名為 module 的模塊
          module={}
           
          -- 定義一個(gè)常量
          module.constant="這是一個(gè)常量"
           
          -- 定義一個(gè)函數(shù)
          function module.func()
           io.write("這是一個(gè)公有函數(shù)!\n")
          end
           
          local function func2()
           print("這是一個(gè)私有函數(shù)!")
          end
           
          return module
          

          Lua提供了一個(gè)名為require()的函數(shù)用來加載模塊,例如:

          require("<模塊名>")
          

          元表

          Lua提供了元表(Metatable)來改變table的行為,有點(diǎn)類似于Javascript中的原型鏈,還為每個(gè)行為關(guān)聯(lián)了對(duì)應(yīng)的元方法。例如使用元表,可以定義Lua如何計(jì)算兩個(gè)table的相加操作a+b,當(dāng)Lua試圖對(duì)兩個(gè)表進(jìn)行相加時(shí),先檢查兩者之一是否有元表,之后檢查是否有一個(gè)叫__add的字段,若找到,則調(diào)用對(duì)應(yīng)的值,__add等字段,其對(duì)應(yīng)的值(往往是一個(gè)函數(shù)或是table)就是”元方法“。

          還有其他各種元方法:

          基于元表的特性(繼承),可以實(shí)現(xiàn)Lua面向?qū)ο缶幊獭?/p>

          協(xié)程

          Lua 協(xié)同程序(coroutine)與線程比較類似:擁有獨(dú)立的堆棧獨(dú)立的局部變量獨(dú)立的指令指針,同時(shí)又與其它協(xié)同程序共享全局變量和其它大部分東西。

          co=coroutine.create(
           function(i)
           print(i);
           end
          )
           
          coroutine.resume(co, 1) -- 輸出:1
          

          文件I/O

          io方法稱為簡(jiǎn)單模式,一次只能處理一個(gè)輸入文件和輸出文件,file句柄形式則可以同時(shí)操作多個(gè)文件。

          錯(cuò)誤處理

          • assert
          1assert(type(a)=="number", "a 不是一個(gè)數(shù)字")
          

          assert首先檢查第一個(gè)參數(shù),若沒問題,assert不做任何事情;否則,assert以第二個(gè)參數(shù)作為錯(cuò)誤信息拋出。

          • error
          error (message [, level])
          

          終止正在執(zhí)行的函數(shù),并返回message的內(nèi)容作為錯(cuò)誤信息。

          • pcall

          Lua中處理錯(cuò)誤,可以使用函數(shù)pcall(protected call)來包裝需要執(zhí)行的代碼。

          pcall接收一個(gè)函數(shù)和要傳遞給后者的參數(shù),并執(zhí)行,執(zhí)行結(jié)果:有錯(cuò)誤、無錯(cuò)誤;返回值true或者或false, errorinfo。

          if pcall(function_name, ….) then
          -- 沒有錯(cuò)誤
          else
          -- 一些錯(cuò)誤
          end
          

          其他

          • lua 不支持自增、自減;
          • 邏輯運(yùn)算符:and、or、not;
          • 關(guān)系運(yùn)算符:~=不等于

          主站蜘蛛池模板: 欧洲精品一区二区三区在线观看 | 中文字幕精品无码一区二区三区| 日本一区二区三区不卡视频| 成人免费视频一区二区三区 | 亚洲一区无码精品色| 亚洲午夜精品一区二区麻豆| 亚洲制服中文字幕第一区| 中文字幕人妻无码一区二区三区| 一区二区在线免费视频| 国产福利一区视频| 濑亚美莉在线视频一区| 麻豆精品人妻一区二区三区蜜桃 | 精品国产免费一区二区三区香蕉| 一区二区3区免费视频| 一区视频在线播放| 插我一区二区在线观看| 东京热无码一区二区三区av| 国产一区二区三区夜色| 亚洲人AV永久一区二区三区久久| 一区二区日韩国产精品| 无码国产亚洲日韩国精品视频一区二区三区| 色一情一乱一伦一区二区三欧美| 亚洲综合一区国产精品| 夜夜精品视频一区二区| 国产一区二区三区日韩精品| 日韩精品一区二区午夜成人版 | 精品无码一区二区三区水蜜桃| 亚洲国产AV无码一区二区三区 | 久久国产香蕉一区精品| 亚洲日韩精品一区二区三区| 人妻无码久久一区二区三区免费 | 日本一区二区视频| 精品国产AV一区二区三区| 亚洲AV成人精品一区二区三区| 亚洲色精品VR一区区三区| 国产熟女一区二区三区五月婷| 亚洲国模精品一区| 中文字幕一区二区精品区| 国产精品久久久久久一区二区三区 | 日韩人妻无码一区二区三区| 亚洲国产精品自在线一区二区|