自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

從前端到全端:JavaScript逆襲之路

開發(fā) 前端
近年來,前端技術(shù)日新月異,前端已經(jīng)不僅僅是網(wǎng)頁,更多的開始由狹義向廣義發(fā)展。 先后涌現(xiàn)出了具備后端能力的node,具備移動開發(fā)能力的react native,具備游戲渲染能力的cocos2d-js,以及iOS上的熱修復(fù)技術(shù)JSPatch等等新技術(shù)。

[[207858]]

背景

近年來,前端技術(shù)日新月異,前端已經(jīng)不僅僅是網(wǎng)頁,更多的開始由狹義向廣義發(fā)展。 先后涌現(xiàn)出了具備后端能力的node,具備移動開發(fā)能力的react native,具備游戲渲染能力的cocos2d-js,以及iOS上的熱修復(fù)技術(shù)JSPatch等等新技術(shù)。 咋一看,幾乎各個(gè)端都被JavaScript攻陷,大有一統(tǒng)江湖之勢。 究竟,JavaScript如何做到上天入地?zé)o所不能?JavaScript真的能一統(tǒng)江湖嗎? 

 

領(lǐng)域

代表技術(shù)

web前端

各類MVVM框架,recat,angular,vue... 

故事要從JavaScript的由來說起。

亂世出英雄:

JavaScript的誕生 

 

背景:

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

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

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

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,以與處于市場領(lǐng)導(dǎo)地位的Netscape產(chǎn)品同臺競爭。JScript也是一種JavaScript實(shí)現(xiàn),這兩個(gè)

JavaScript語言版本在瀏覽器端共存意味著語言標(biāo)準(zhǔn)化的缺失,對這門語言進(jìn)行標(biāo)準(zhǔn)化被提上了日程,在1997年,由Netscape、SUN、微軟、寶藍(lán)等公司組織及個(gè)人組成的技術(shù)委員會在ECMA(歐洲計(jì)算機(jī)制造商協(xié)會)確定定義了一種名叫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è)部分: 

 

名稱

描述

ECMAScript

(語言核心)

即是基本語法,代碼塊,作用域,數(shù)據(jù)類型等。

 

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

 

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

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

 

瀏覽器

組成部分

描述

排版引擎

(內(nèi)核)

全稱是Layout engine,也稱為瀏覽器內(nèi)核(web browser engine)、頁面渲染引擎(rendering engine)或樣版引擎)是一種軟件組件,負(fù)責(zé)獲取標(biāo)記式內(nèi)容(如HTML、XML及圖像文件等等)、整理信息(如CSS及XSL等),并將排版后的內(nèi)容輸出至顯示器或打印機(jī)。所有網(wǎng)頁瀏覽器、電子郵件客戶端以及其它需要根據(jù)表示性的標(biāo)記語言(Presentational markup)來顯示內(nèi)容的應(yīng)用程序都需要排版引擎。

JavaScript引擎

JavaScript引擎是一個(gè)專門處理JavaScript腳本的虛擬機(jī),一般會附帶在網(wǎng)頁瀏覽器之中。常見的有SpiderMonkey,V8等。

 

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

 

瀏覽器名稱

排版引擎

(內(nèi)核)

JavaScript引擎

Google Chrome

使用webkit排版,借鑒Safari和Firefox部分成果

V8

 

其他JavaScript引擎,Rhino,由Mozilla基金會管理,開放源代碼,完全以Java編寫,可以看做SpiderMonkey的Java版。 注意:webkit不單單只是一個(gè)排版引擎,webkit = 排版引擎 + JavaScript引擎。 > 所以,JavaScript是動態(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對象、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)鍵是:值類型相互對應(yīng),Obj映射class的一個(gè)實(shí)例,function映射一個(gè)句柄或者引用 

 

JavaScript

C++

Java

number

int/long/float/double

int/long/float/double

 

 

JAVASCRIPT數(shù)值型中的坑

JavaScript內(nèi)部,所有數(shù)字都是以64位浮點(diǎn)數(shù)形式儲存,即使整數(shù)也是如此。所以,1與1.0是相同的,是同一個(gè)數(shù)。

這就是說,在JavaScript語言的底層,根本沒有整數(shù),所有數(shù)字都是小數(shù)(64位浮點(diǎn)數(shù))。容易造成混淆的是,某些運(yùn)算只有整數(shù)才能完成,此時(shí)JavaScript會自動把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位:符號位,0表示正數(shù),1表示負(fù)數(shù)

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

*第13位到第64位:儲存小數(shù)部分(即有效數(shù)字) 符號位決定了一個(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ù)之中,最長可能為52位。因此,JavaScript提供的有效數(shù)字最長為53個(gè)二進(jìn)制位(64位浮點(diǎn)的后52位+有效數(shù)字第一位的1)。

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

精度最多只能到53個(gè)二進(jìn)制位,這意味著,絕對值小于2的53次方的整數(shù),即-(253-1)到253-1,都可以精確表示。 而大部分的后端語言,C++、Java、Python等的long型都是可以支持到64位,因此long型數(shù)據(jù)從后端語言傳給JavaScript會發(fā)生低位截?cái)?。遇到這種情況一般使用String處理,如需要在JavaScript中做long型計(jì)算,需要自行實(shí)現(xiàn)計(jì)算器。

 

有了自行往JavaScript引擎中注入的想法,接下來就是分析可行性。 大部分是JavaScript引擎是使用C++編寫,如果自己的程序使用的是C++可以很方便的進(jìn)行注入,如果是OC,可以使用OC和C++混編的形式。 其他語言怎么破? 要在一門靜態(tài)語言上與動態(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,對外暴露一個(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í),會調(diào)用暴露出來的構(gòu)造器接口,得到一個(gè)實(shí)例對象。不管是裝載JS模塊還是裝載C++模塊,得到的都可以看做是一個(gè)Module Object,node會將裝載完的模塊緩存到binding_cache中,下次在別處的代碼中使用require裝載模塊時(shí),就會先去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的動態(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è)膠水層??梢钥醋鲂∈昵暗膎ode吧。

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

 

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

2、.get指明是處理GET請求,RESTful;

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

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

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

categorynode.get.desc.xml

 

categorynode.get.js

 

categorynode.get.html.ftl

 

categorynode.get.json.ftl

 

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

 

React Native中的橋接

React Native目前也是異?;鸨琑N程序的運(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)存頁(因而無法動態(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非常方便。對于做需要經(jīng)常更新的渲染場景,C++是靜態(tài)語言,每次修改都需要重新編譯才能運(yùn)行,顯然是不合適的。自然也就想到了腳本語言,lua和js,兩者有些類似,都是動態(tài)語言,只需要集成一個(gè)運(yùn)行引擎,提供一個(gè)運(yùn)行的容器即可運(yùn)行,同時(shí)通過引擎注入底層方法供腳本調(diào)用即可。lua好處是精簡,語法精簡,引擎頁很小很精簡,所以不可避免的代碼量會比js多,同時(shí)學(xué)習(xí)成本比較高。js的好處是有ECMAScrtpt的核心,語法比較豐富,同時(shí)有支持一些高級屬性。在cocos2d-js中,cocos2dx(C++)集成了SpiderMonkey(C++)作為JS運(yùn)行引擎,中間做了一個(gè)膠水層既是JS Binding,通過引擎注入了一個(gè)cc的全局對象,映射的是底層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,對開發(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 是動態(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 端在啟動 JSPatch 引擎時(shí)會創(chuàng)建一個(gè) JSContext 實(shí)例,JSContext 是 JS 代碼的執(zhí)行環(huán)境,可以給 JSContext 添加方法,JS 就可以直接調(diào)用這個(gè)方法。本質(zhì)上就是通過JavaScriptCore引擎注入,暴露OC的方法供JS調(diào)用來實(shí)現(xiàn)動態(tài)修改OC的反射。

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

1、集成JavaScriptCore引擎;

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

3、通過JS修改OC反射。

 

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

關(guān)于JavaScript引擎:

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

 

JavaScript引擎

iOS

Android

JavaScriptCore

Interpreter only(僅解釋器模式)

Interpreter and JIT(解釋器模式和即時(shí)編譯模式)

 

因?yàn)閕OS平臺不支持JIT即時(shí)編譯,而V8只有JIT模式,所以V8無法在iOS平臺使用(越獄設(shè)備除外,想體驗(yàn)iOS JIT的同學(xué)可以自行越獄)。 所以,目前可以做到橫跨iOS和Android雙平臺的JS引擎,只有兩款,即是SpiderMonkey和JavaScriptCore。 JavaScript引擎會受很多東西影響,比如交叉編譯器的版本、引擎的版本和操作系統(tǒng)的種類等。

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

至此,JavaScript從立足于前端,到征戰(zhàn)全端的逆襲之路,可以總結(jié)為“攜引擎以令天下”。 不足之處,還請各位看官輕拍~ 

責(zé)任編輯:龐桂玉 來源: Web開發(fā)
相關(guān)推薦

2020-11-17 07:14:50

技術(shù)總監(jiān)

2017-04-18 14:25:54

Excel實(shí)戰(zhàn)數(shù)據(jù)

2015-07-08 11:22:16

程序員炒股

2020-06-11 17:30:49

2019-07-09 09:48:41

前端開發(fā)技術(shù)

2014-08-07 10:45:31

長尾市場華為

2019-06-26 08:20:19

JavaScriptWeb開發(fā)

2017-11-22 09:14:50

HPC數(shù)據(jù)超算

2018-12-20 08:48:19

2014-09-03 16:04:17

傳統(tǒng)數(shù)據(jù)中心逆襲

2017-04-19 17:16:14

黑產(chǎn)黑色產(chǎn)業(yè)鏈網(wǎng)絡(luò)黑產(chǎn)

2012-10-19 11:05:03

思科OpenStackCitrix

2013-07-26 13:40:20

程序員轉(zhuǎn)型轉(zhuǎn)型賣水果轉(zhuǎn)型逆襲

2022-01-19 09:00:51

UI前端手機(jī)開發(fā)

2018-12-19 08:24:32

2015-08-04 14:22:43

虛擬化OpenFlowSDN

2020-07-13 08:40:21

BAT模具設(shè)計(jì)

2013-07-23 09:42:21

IBMNetflix

2015-08-10 10:20:09

虛擬化OpenFlowSDN

2013-11-13 14:42:05

手游海外市場
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號