腳本ua
1. jQuery $(window).scroll事件出現問題
web前端開發 20 年變遷史,讓我們來看看這20年裡,web前端究竟經歷了哪些變革,web前端在這20年裡又有哪些突破和成就,怎麼樣看待這20年的web前端開發!
1990年,第一個Web瀏覽器誕生,而WWW的誕生直接拉開前端史的序幕。
從靜態頁面到Java,從依賴後端到自主開發,前端開發者從不被重視的「頁面仔」逆襲為如今很多前端工程師的薪資比後端還高,從前端技術由國外開發者主導到如今國內自主產生的小程序技術,我們走了20年。
了解web前端:http://www.cnite.cn/qianan/
作者 | 司徒正美
責編 | 伍杏玲
1990 年,第一個Web瀏覽器的誕生;1991 年,WWW誕生,這標志著前端技術的開始。
在這將近20年的前端發展史中,我們經歷了從最早的純靜態頁面,到Java跨時代的誕生;從PC端到移動端;從依賴後端到前端可自由打包開發;從早期的網景Navigator瀏覽器到現在各家瀏覽器百花齊放……
我們經歷了前端的洪荒時代、Prototype時代、jQuery時代 、後jQuery時期、三大框架割據時代,這其中均是由國外開發者主導,直到如今的小程序時代,才是中國開發者獨創的。
這是漫長的技術儲備下的成果,最終促成了良好的技術成長收獲。期間的前端發展之路,崎嶇艱難:
洪荒時代(1990~1994年)
在1990~1994年期間,前端界發生的大事有:WWW(World Wide Web)的誕生、瀏覽器的誕生、Java的誕生,沒有專業的前端,頁面全是由後端開發的。
1990年,萬維網之父蒂姆·伯納斯-李(Tim Berners-Lee)在NeXT電腦上發明了第一個Web瀏覽器。
1991年8月6日,Tim在alt.hypertext新聞組貼出了一份關於World Wide Web的簡單摘要,這標志了Web頁面在Internet上的首次登場。
最早的Web主要被一幫科學家們用來共享和傳遞信息,全世界的Web伺服器也就幾十台。由於僅是用來傳遞信息,從可視化方式或從傳遞數量上看,僅比電報強一點點。
當時還沒有Java,用的是純靜態的頁面。
1993年,CGI(Common Gateway Interface)出現了,人們可以在後端動態生成頁面。
Perl由於跨操作系統和易於修改的特性成為CGI的主要編寫語言。當然,CGI也支持其他支持標准輸入輸出和環境變數的語言編寫,比如Shell腳本、C/C++語言,只要符合介面標准即可。
但顯然,頁面的內容更新完全由後端生成,這帶來一個明顯的缺憾:每次更新都要整頁刷新,加上早期的網速情況,這個操作是非常慢的。因此針對這情況,人們從多方面著手改進:編寫語言的升級、瀏覽器的升級、HTML的升級。
1994年,網景公司成立,發布了第一款商業瀏覽器Navigator。自從這款瀏覽器面世後,微軟推出IE瀏覽器。雖說有競爭才有發展,但這也埋下了Java分裂的種子。
(1994 年,網景瀏覽器的截圖)
同年,PHP誕生。PHP能將動態的內容嵌入到HTML中,提升了編寫頁面的效率與可讀性,其性能也比一般的CGI高。PHP的界定符、循環語句等的發明,深刻影響了後來的ASP、JSP,乃致後來的Java前端模板引擎。
1994年10月,W3C小組也成立了,他們負責HTML的發展路徑,其宗旨是通過促進通用協議的發展。
待這一切就緒後, Java於1995年誕生了。
傳聞,網景工程師布蘭登·艾克(Brendan Eich)只花了10天時間設計出 Java 語言,近乎上帝七日創造世界那麼高效。但也因為工期太短的緣故,導致許多瑕疵,因此一直被正統傳序員所嫌棄,直到Ajax的出世,才讓人們找到理由忍受它的畸形。早期的瀏覽器都配有一個選項,用來禁止Java語言運行。
Java主要語言特徵[1]:
借鑒C語言的基本語法;
借鑒Java語言的數據類型和內存管理;
借鑒Scheme語言,將函數提升到"第一等公民"(first-class citizen)的地位;
借鑒Self語言,使用基於原型(Prototype)的繼承機制。
時下,靜態語言大行其道,類與介面被證明是構建大工程的最佳實踐,人們想不出沒有類的語言如何編寫業務。因此當時的微軟也打造了另一門運行於瀏覽器的語言——VB。
如果繼續細探Java的能力,你會發現它早期真的非常空洞,一門沒有靈魂的語言,沒有包管理機制,也沒有像Java與C++那樣的打輔助用的SDK,內置的方法也屈指可數。比如說數組方法,早期只有push、pop、shift、unshift、splice、slice、sort、reverse、concat、join等操作。動態調用方面,Function的apply、call操作還沒有出現!
早年的偷懶,導致後來不得不補課:到了2019年,數組上的原型方法,是原來3倍。
除了方法缺乏,還有性能問題,大家討論用eval還是Function,用哪種循環方式,用parseInit還是~~,就是為了那一點點的性能提升。例如jsperf.com,就是一個專門研究Java性能的網站。
因此Java誕生後,其兩大任務就是完善語言特性與提高性能。這兩座大山分別由著名的prototype.js與jQuery來搬掉。
在搬掉之前,前端界還有一個曲折實踐——第一次瀏覽器戰爭,並由其發展而來UA嗅深技術。
瀏覽器戰爭(1994~2005年)
瀏覽器戰爭一共打了三場,IE瀏覽器vs網景瀏覽器、IE瀏覽vs火狐瀏覽器、IE瀏覽器vs谷歌瀏覽器。
第一場瀏覽器之戰打得尤其激烈。
微軟的IE瀏覽器發布於1994年,但此時的網景已經佔領絕對優勢。微軟在落後的情況,反編譯Netscape的源碼,推出IE與J。但是由於Bug非常多,大家不願意為IE開發網站,因此發掘出UA,專門過濾掉IE瀏覽器。
UA即Navigator.userAgent ,是用一個字元串來記錄用戶當前運行在什麼操作系統與瀏覽器中。當前IE3的UA是這樣的:
Mozilla/2.0 (compatible; MSIE 3.02; Windows 95)
程序判斷UA信息,假如發現當前運行的環境是IE瀏覽器的話,就提示用戶用網景瀏覽器打開。因此微軟不得不讓自己的UA盡量偽裝成網景的UA,欺騙用於檢測UA的腳本,達到IE瀏覽器可以跑這些網站的目的。
最終,第一次瀏覽器之戰以微軟勝利,Netscape被美國在線收購,而落下帷幕。
第一次瀏覽器戰爭年代非常久遠了,但其結局告訴我們,其實技術強弱並不重要。那時技術保護並沒有這么重視,否則微軟的行為可能會被告(谷歌的openSDK僅抄襲幾十行代碼,被Oracle公司訴訟賠88億)。
第一次瀏覽器戰爭帶來了一個問題:盡管當時有ECMA-262(Java規範文檔)與W3C(HTML與CSS的規範文檔),微軟卻沒有照規范來實現Java、HTML與CSS,導致前端兼容問題的誕生。所以CSS Hack、瀏覽器判定、特性偵測,這些技術就應運而生。
這個時代最著名的人物是Dean Edwrad,他是最早的近乎完美解決事件綁定的兼容性大神,其addEvent()內置於jQuery最早的版本中。jQuery的作者John Resig看到其超強的技藝,最後放棄推出大而全的框架,專攻選擇器引擎。
Dean Edwrad的IE7.js、IE8.js是早期處理瀏覽器兼容的良葯,可以說是一切Polyfill[2]的起源。他寫了大量的Hack, 比如在IE如何測量元素的寬高,許多操作DOM的兼容。
這時期太早,中國基本沒有參與這次瀏覽器戰爭。
Prototype時期(2005~2009年)
Prototype是Sam Stephenson寫的一個非常優雅的Java基礎類庫。他是Ruby的大牛,因此Prototype的許多方法名都是來自Ruby界。
Sam Stephenson最大的貢獻是發掘了Prototype與創造了Function.prototype.bind,在數組上也寫了一大堆方法,其中許多被標准化了。
同期的MooTools也是Prototype的方法,當時,大家還在前端論壇為這個爭吵。還有前端工程師喜歡在當時很出名的前端聚集地——藍色理想(現淪為設計師網站)上,討論如何扒腳本、分享彈層、日歷等小組件的技術,這在當時已經是非常了不起的事。
Prototype當時還解決兩大問題:動畫特效與Ajax請求。動畫特效是由aculous提供,我們現在所熟知的各種緩動函數,各種特效的命名與大致的運行形態,都是由aculous確定下來的。
在早期,谷歌就開始使用iframe實現頁面刷新。
2005 年2月,傑西·詹姆士·賈瑞特(JesseJamesGarrett)發表了一篇名為《Ajax:一種Web應用程序開發的新方法》的文章後,Ajax被挖掘出,大家才開始重視起這技術的應用。
例如IE下的ActiveXObject("Microsoft.XMLHTTP"),這是IE創建Ajax引擎的。假如當時有工程師開發出一個核心庫,如果不包含Ajax的封裝,便不好意思發布出來。
一些Ajax書藉
當時前端開發模式是選擇一個核心庫,找一些組件,或者扒別人的腳本進行開發
Prototype的源碼挺好理解的,代碼量也少,只有5000多行,裡面的每個方法也很易扒出來,因此一些大公司總有高手能創造自己的Prototype。
但前端開發還是離不開後端,因為前端沒有模塊機制,當時我們需要用PHP進行打包。打包是雅虎34條軍規之一,可以減少請求數。打包的同時也可以進行混淆,防止代碼小偷來窺探。
N年前,前端面試必問的題目:
模塊化的雛型, 在注釋中標注它的依賴
這個時期,還沒有前後端分離,可國內一些帶著深厚後端背景的高手已經入場。
jQuery 時期(2009~2012年)
2006年,jQuery發布,它當時的競爭對手很多:Dojo、Prototype、ExtJS、MooTools。
所以那時jQuery的宣傳口號僅能說是它的性能上升了100%、200%、300%。直到2009年,Sizzle選擇器引擎研發成功,jQuery才取得壓倒性的優勢。
當時前端界首要面對的是瀏覽器兼容性問題,jQuery在處理DOM兼容上真是知微見著, 發掘出大量的DOM/BOM兼容方案(例如Dean Edwrad的addEvent(), IE的px轉換方案,domReady的doScroll方案,globalEval的兼容方案等)
jQuery也打破了前端開發者的編程思維,之前是按照後端的開發思路來的:做一個業務就先封裝一個類,有了這個類後,再想辦法傳入一個DOM,然後再通過類方法操作DOM。而jQuery是DOM為中心,開發者可以選一個或多個DOM,變成jQuery對象,然後進行鏈式操作。當時為了改變用戶的思維,國內的高手寫了不少文章來引導大家。
其次,開發者們已開始注重前後端分離,並要求不能污染Object原型對象,不能污染window全局變數。這樣,jQuery只佔用兩個全局變數。
再次,jQuery非常輕量級,採用Dean Edwards編寫的Packer壓縮後, 大小不到30KB。並且裡面實現得非常精妙,以令人瞠目的手段解決各種兼容痼疾。
為了學習這些技巧,高手們翻了一遍遍jQuery的源碼,所以網上有大量關於其源碼詳解的書藉。甚至前端工程師在面試時也會被考到jQuery的源碼實現,這樣,jQuery在國內更加流行。
jQuery的流行間接帶來以下的發展:
促使人們對CSS1~CSS3選擇器的學習
促進了瀏覽器原生選擇器引擎document.querySelectorAll、Element.matches的誕生
提高人們對domReady(DOMContentLoaded事件)的認識
促進了Promise與requestAnimateFrame 的誕生
最重要的是降低前端門檻,讓更多人進入這行業,前端工程師的隊伍越來越壯大。
這樣的話,不斷涌現出優秀的工程師,他們創造了大量jQuery插件與UI庫。為後jQuery時代,人們研發前端模塊載入、統一非同步機制、 打造大型MVC框架, 甚至伸向後端,接管打包腳本而發明Node.js,來騰出大量時間。
這個時期涌現了大量jQuery-like的庫,其中最著名的是Zepto.js。Zepto的出現也標志著我們進入移動互聯網時代。那時配套出的著名庫還有iScroll、fastclick、Lazy Load、Modernizr、fullPage。
jQuery的鏈式操作風麾一時,也帶來許多問題,當Ajax出現依賴時,就不可避免就出現回調地獄。因此針對這方面的討論,誕生Deffered與Promise。有關回調地獄的討論,在後來講Node.js非同步處理時,將會再一次熱烈地討論。因此太陽下沒有新事,我們總是遇到相似的問題。
jQuery如此多的選擇器也法維護,隨著越來越多人涌現這行業,頁面的交互也越來越復雜,從Web Page向Web App進化,新的趨勢帶來新的開發方式。
後jQuery時期(2012~2016年)
這時期以RequireJS的誕生為起點,以RN的出現結束。同時解決了前端的模塊定義問題,模塊打包問題(通過Node.js),Java不依靠其他語言創造了一套自己的工具鏈。
jQuery的出現讓前端工程師開發更加輕松,假如工程師想實現一個功能,現搜索出一個jQuery插件來實現。那時候大家在前端網站就整天介紹jQuery插件,很少討論一些底層的實現。
前端工程師通常編寫一個頁面,會引入十多個乃至幾十個jQuery插件,頁面上塞滿了標簽。眾所周知,瀏覽器是單線程,的載入,會影響到頁面的解析與呈現,導致著名的白屏問題(當時前端用力過勐,body中的所有東西都是動態生成的)。
jQuery另一個問題是全局污染,由於插件的質量問題,或者開發的素質問題,這已經是IIEF模塊或命名空間等傳統手段無法解決了。
於是一些優秀的前端工程師們決定從取經後端,引入模塊機制。早期,這種模塊機制在Dojo、EXT這些框架中都是內置的,但是顯然說服不了另一個框架的用戶用對方的模塊機制,於是有人立志要統一這種模塊定義方式,成立了CommonJS。
但不料,CommonJS內部也有派系,誰也說不服對方。終於有一個人忍不住自己獨立開發出RequireJS,其模塊規范即為AMD。 AMD最大的優勢是它支持各種插件,且簡單明了,並且提供shim機制載入以非AMD規范編寫的Java代碼。
但在CommonJS誕生很久一段時間後,在後端的Node.js出現時才有用武之地。而國內,則流行另一種規范風格,背靠阿里的大旗,有人推出了SeaJS,號稱其規范為CMD。其實無論國內還是國外,都產生許多模塊載入器,但最後還是被淘汰了,規范一個就夠了,不宜過多。
但是前端工程師的創造力就是這么驚人,從無到有,再到泛濫成災,一年足矣。這可能與前端代碼是開源的原因。最後有人統一了前兩種規范(AMD、Node.js模塊),同時還支持老式的「全局」變數規范。
自此,Java開發模式煥然一身了,大家只要在代碼外麵包一層就可以全世界通用,不用提心全局污染的問題。
其次,jQuery開發者需要解決大段HTML的生成問題,之前jQuery有$.html, $.append, $before等方法,可以將一大段符合HTML結構的字元串轉換成DOM再插入到頁面上。
但現在我們想分離出來,讓HTML獨立到不同的文件中,然後插數據,這就是前端模板。前端模板的情況與模板規范一樣,從沒有到多如芝麻的境地。這時篩選一個好用且性能高的模板是一件讓前端工程師頭疼的問題,那時網上有許多評測文章來介紹它們。
前端模板技術可以用一個公式來描述:
HTML = template(vars)
有了前端模板後,又誕生了前端路由,基於它們,人們發明一個新詞彙SPA。作為這個時代的尾聲,來自Ruby界的高手Ryan Dahl發明了Node.js。 前端工程師們歡唿:可以不用傳統的後端就能自己寫一個網站了!
Node.js的發展就不詳述上,很快它就冒出海量模塊、路由、狀態管理、資料庫、MVC框架都有了。這時,前端就缺自己的MVC框架了。Node.js轉眼就十歲生日了。
著名的MEAN架構,是Java全棧開發的先鋒。當時涌現了大量的MVC與MVVM框架。最先火起來的是Backbone.js,使用純正的MVC模型, Backbone.js是jQuery最後的支持者,它強依賴於jQuery。
Backbone.js的作者還搞了另一套編譯語言Coffee, 裡面的箭頭函數、類機制、 解構賦值等語法糖都深深影響了後來的ES6。
接著下來是谷歌的Angular,微軟的Knockout.js,蘋果的Ember.js這三個MVVM框架,MVVM就是比MVC多一個數據綁定功能,但這數據綁定功能是非常難實現。Knockout是使用函數代替屬性的技巧實現,它的設計影響到後來的Mobx;Ember.js是基於Object.defineProperty;Angular是將函數體轉譯成setter()、getter()函數。
大公司的介入,對個人開發者影響是很大,畢竟大家都愛迷信大公司,因此局面一下子就穩定下來。大公司還帶來了全新的開發模式,早期都是找一個核心庫,再搜刮一大堆插件,然後自己寫業務代碼,最後後端打包。
大公司將後端開發經驗挪用過來,用Node.js開發了一套CLI,裡麵包含了腳手架生成, 打包腳本、語法風格檢測、環境變數插入,代碼復雜度檢測,代碼提交時自動跑單元測試, 圖片與JS壓縮等功能。ESLint、JSLint、JSHint、CSS Lint、 htmllint等就是那時期出現的。
但CLI的出現導致了前端的分裂,以前大家都使用jQuery,但自CLI幫你建好項目的那一刻起,就將你劃歸某一子陣營,你是Angular?Ember.js?還是jQuery?對了,jQuery沒有大公司支撐的陣營被快速邊緣化。
對於個人開發者,他們是沒有能力開發這么功能完備的CLI,於是出現了Code Climate、Travis CI、CircleCI這樣的平台。它們的出現標志著jQuery小作坊時代的終結了。
CircleCI官網
前端開發者也出現分化:有些人轉向後端,出現了CNode的門戶網站。另外一些人開始搞工程化。一時間出現上百種構建工具,出名的有Grunt、Gulp、FIS3、webpack、 Rollup、npm-。
你方唱罷我登場,這些構建工具均會經歷時代的考驗,如大浪淘沙般,最後存活得僅為寥寥。
因此在這場工程化得盛宴中,註定把許多低層次的jQueryer淘汰掉。jQueryer在空閑之餘培育出的前端模板、前端路由、MVC框架、模塊載入器、Node.js構建工具,卻不料最終成為它自己的挖墓人。
jQuery的時代一去不返了,再沒有人關心拖堂拖了N年的Bootstrap 4終於發布了,沒有人知道jQuery3.5的瘦身計劃,也沒有人問jQuery的源碼,漸漸地,大家不關注jQuery的工具鏈了。
三大框架割據時代(2016~至今)
React是突然爆發的,雖然它是與Angular是同時期發布,但因為JSX怪異的語法讓人們遠離它。此時已經進入移動互聯網的中期,大公司都有自己的App,或者基於原生,或者基於Hybird。
Hybird是用WebView載入一個網站或一個SPA。
由於原生成本太貴,需要招兩套班子,一套安卓的,一套iOS的;而Hybird則一直存在性能問題。於是在2017年,Facebook推出了React Native(RN)。
RN的性能不比原生差多少,比Hybird能好些, 其次使用JSX開發界面比原生的快; RN 只需要低成本的前端開發人員就能上手了。中國國內經過瀑布流(圖片導購)、團購、P2P、區塊鏈等全新商業模式的開發浪潮後,前端人員數量大增。現在,他們只要稍微培訓就可以轉型為App開發。
在開發RN的過程中,人們開始了解React一系列的優勝之處。比如JSX背後的虛擬DOM技術,雖然事實證明虛擬DOM不會帶來性能的巨大優勢,但保證了你怎麼寫其性能不會太差。
React為了引入JSX,必須需要引入編譯,這又間接促成Babel與webpack的壯大。尤其是Babel, 讓我們在很舊的瀏覽器中使用非常新的語法,甚至一些還沒有定案的語法。React從14升級到React 15,強制使用class語法,讓這個推了好久的語法糖終於大規模落地。
之前如果Java想使用類,只能自己模擬類,由於沒有官方的實現,只能任由各優秀工程師發揮。而普通人想用好類,需要了解很復雜的Prototype機制。
現在只用幾個新關鍵字就可以得到這一切。
如果對比Python 2與Python 3間的升級,Java實在太辛運了!針對CSS邏輯功能過弱的問題,我們也有了新的解決方案:Less、Sass、PostCSS與CSS Moles!
谷歌在發布Angular的同時,也發布了一個叫Polymer的框架,那時它想推廣一種叫Web Components的瀏覽器自定義組件技術。這其實是微軟在IE5就玩剩的HTC技術的升級版。雖然它沒有火起來,但它將、Style、Template三種內容混在一個文件的設計,啟發一個留美華人,再結合當時的Backbone.js、Angular等設計,Vue.js橫空出世。目前,這是國人最成功的前端框架了。
除此之外,國人也弄了好幾套迷你React框架與迷你Vue框架。這有點像jQuery時代,大家瘋狂做迷你jQuery框架一樣。
總的來說,最有創造力的是React團隊,做出狀態管理器、CSS-in-JS、Flow靜態類型檢查、devTool、Fetch、前後端同構、Fiber、suspend、並發渲染等名詞層出不窮。其中,狀態管理器擁有上百套, CSS-in-JS也擁有上百套,Flow則讓前端嘗鮮到介面編程的好處,間接推動發Type發展。這三大框架無法比拼個一二出來:Vue.js有國人的擁躉,React與Angular有大公司光環。
三大框架的纏斗從PC領域擴展到移動端:React有RN, Vue.js有Weex,Angular有ionic。想當年我們為了兼容瀏覽器,攢了一大堆瀏覽器偵探的Hack,全部貶值為垃圾了。
在這時期,一種全新的後端渲染崛起,稱之為前後同構,既擁有早期SEO的功效,又能復用大量的業務邏輯。隨著國內移動互聯網的發展,獲客成本提高,各種有效的商業模式都進入紅海,但只有頭部用戶能賺到錢,馬太效應越來越嚴重,純粹的技術解決方案已經無法滿足商業訴求了。
小程序時代(2017~至今)
小程序時代與三大框架的時代幾乎重合,但是出自不同一批人,決戰的平台也不一樣。
一直以來前端技術都是由國外開發者主導的,即便是Vue.js也是由美國的華人創造的。但是國內外的技術更新是存在代差,國內通常延期兩三年,這個時間差可以讓一些模仿者得以生存(如SeaJS、FIS、avalon)。但隨著封閉的時間越來越長,國內肯會也會誕生自己的轉有物種。小程序就是其中之一。
小程序的出現有著明顯的商業訴求,因為馬太效應,一些超大流量的App誕生了。這些大流量App集成了許多功能,但顯然公司再多員工,也無法所有功能全是自己弄,於是產生小程序這種「外包」的手段。
小程序是國內前端技術的一次厚積薄發:底層運行的迷你React的虛擬DOM, 內置組件是使用Web Component,API來源於Hybird的橋方法,打包使用webpack,調試台是Chrome console的簡化版, WXML、WXSS的語法高亮也應該是webpack或VS Code的插件, 模塊機制是Node.js的CommonJS……其中最值得一提的是微信開發者工具,以後開發者工具成了各種小程序/快應用的標配。
但微信小程序一開始的復用能力非常弱,沒有類繼承,不能使用npm, 不支持Less、Sass, 因此基於它的轉譯框架就應運而生。第一代譯轉框架是wept、WePY、mpvue,它們無一例外是Vue風格的。因為WXML的模板指令與Vue非常相似,只是改一下就能兼容。當時也出現了一個MINA的框架,聽說是微信團隊開發的,可以單獨架起Node.js後端,讓小程序運於瀏覽器中,方便做單元測試。
第一代轉譯框架主要是基於Template標簽實現組件機制,自定義組件機制是很後的事了。這就造成了利用第一代轉譯框架編寫的小程序項目很難升級。那時候是個人開發者的天堂,這些框架都是某一大牛獨力開發的。
第二代轉譯框架是大公司主導的,因為需要兼容的小程序越來越多,網路、支付寶、位元組跳動、小米、華為等公司都推出自己的小程序和快應用。個人開發者很難憑個人力量去開發轉譯框架,這時候各大團隊紛紛推出自己的輪子:如京東的Taro、滴滴的Chameleon網易的Megalo、去哪兒網的nanachi、網路的Okam等。
在這個時期,Angular顯然落伍了,一是Angular升級太快,國內的高手還沒有消化好,新一版的Angular又發布了。二是國內缺乏迷你Angular的輪子,導致龐大的Angular無法塞進小程序中。
國外谷歌發布了Flutter跨平台轉譯框架,但是它的編寫語言是Dart,它也無法跨界到小程序中。
未來不僅國內一線巨頭爭奪小程序,二三線的巨頭也可能會加入小程序的混戰中,例如有人稱360也在打造自己的小程序平台。小程序這種新的流量變現模式深刻地影響了國內的互聯網布局。
結語
當初Java被誤解為最糟糕的語言,時至今日它是最流行的語言:GitHub 60%的開源項目都是與Java有關。
以前,從事這行業的人被稱為頁面仔,現在他們的起薪有的比PHP、JAVA、C++等後端還高。甚至有人說,「任何可以使用Java來編寫的應用,最終會由Java編寫。」
我們前端開發者觸及的領域不僅僅是瀏覽器,還可以做後端,做桌面端,做手機端,做小程序端,前端開發者的性價比越來越高,越來越重要。可謂是時代造英雄。
筆者有幸成為前端開發者大隊伍中的一員,也堅信我們前端開發者以後的路會越來越寬,越來越好走。
資料:
[1]:計算機和編程語言的發展歷史
[2]:Polyfill是一塊代碼(通常是 Web 上的 Java),用來為舊瀏覽器提供它沒有原生支持的較新的功能。
作者簡介:司徒正美,擁有十年純前端經驗,著有《Java框架設計》一書,去哪兒網公共技術部前端架構師。愛好開源,擁有mass、Avalon、nanachi等前端框架。目前在主導公司的小程序、快應用的研發項目。
本文鏈接:http://www.cnite.cn/qianan/share/20198308.html
2. lua腳本怎麼取出自己想要的的部分字元
你好,以前沒接觸過lua,剛自己試了一下,就按照你問題中的"23^Hello^你好^2000^world.txt"這個字元串為例,以^為分隔符來說吧:
---------------start---------------
str = "23^Hello^你好^2000^world.txt"
list = table.pack()
for w in string.gmatch(str, "[^^]+") do
print(w)
table.insert(list, w)
end
---------------start---------------
解釋:代碼共6行,
第1行:定義一個變數str,內容為"23^Hello^你好^2000^world.txt",這也是我們要處理的字元串.
第二行: 定義一個空列表,它是用在下面的for循環中,存放以"^"作為分隔符的每一部分
第三行:簡單來看是個for循環,深入一點來看,也就是string.gmatch(str,"[^^]+")這部分需要解釋一下,它表示調用的是string庫的gmatch()函數,這個函數有兩個參數,第1個參數為要處理的字元串,咱們這里就是上面定義的str,第二個參數就是我們要在這個字元串中匹配什麼樣的內容,這里的匹配內容寫的是"[^^]+",學過正則的很好理解,單純的[abc]表示匹配任意單個字元a或b或c,有一點特殊的是一旦[]中的字元是以^打頭的,則表示匹配任意非[]中列出的字元,如[^abc]表示匹配任意除abc外的其它任一字元,所以[^^]解釋為匹配除^外的任一字元,舉例來說,如果我們有字元串"23^Hello",如果用[^^]匹配的話,最終得到的是7個單個字元,即"2","3","H","e","l","l","o",顯示這不符合我們的題意,所以在這基礎上改進了一下,即在其後又加了個+號,[^^]+,這里的+號表示盡可能多地匹配它前面內容,這里也就是盡可能多地匹配[^^],所以[^^]+在處理"23^Hello"的時候,結果得到的就是"23","Hello".這里關於用到的這個正則說的不是太清楚,多練練就明白了。最後,第3行把函數部分給替換掉後,可以理解為:for w in [23,Hello,你好,2000,world.txt],每次從[]中取一個值賦給w,然後執行for下面的語句,接著往下看
第4行,接第3行尾,就是把每次賦給w的值都列印出來
第5行,將每次賦給w的值都追加到列表list中
第6行,for循環語法上的閉合關鍵字,這個沒啥說的
到此,我們得到了一個列表值為[23,Hello,你好,2000,world.txt]的list,此時我們就可以使用list[n]來取我們想要的值了 。
*.如果你要問上面最3條最後不都有[23,Hello,你好,2000,world.txt]了嘛,為啥還要那麼麻煩,直接使用string.gmatch()函數不就行了嘛,其實第3條結尾我那麼寫只是為了讓你好理解,實際上gmatch()函數的返回值並不是列表,而是一個可迭代的函數,而for循環的作用就是把gmatch()函數返回的這個可迭代的函數中的每個元素都取出來並賦給列表list
*.說的有點啰嗦了,希望對你有幫助吧,另外,我從沒用過lua,也是剛查了查,自己實踐了一下,希望不會形成誤導
3. 智慧樹油猴腳本不起作用
出現這種情況有兩種可能,一是腳本沒開啟。 二是腳本已經失效。
碰到這種情況,一般有兩種解決辦法:
1、等待腳本作者更新腳本,或者更換其他腳本 用戶主要是靠腳本獲取網路雲文件的下載直鏈,如果腳本被官方限制使用,腳本就會失效,idm自然也下載不了網路雲文件。
這時可以等待腳本作者更新,如果不想等,可以登錄「greasyfork」網站,搜索「網路網盤/網路雲/網路下載直鏈/網路」等,找到相關腳本並安裝即可。 通常腳本與腳本不會沖突,所以不用擔心安裝多個腳本導致idm下載失敗的情況發生。 另外在安裝其他腳本時,要注意腳本的使用的說明,不同腳本對idm的設置要求不同,比如有些腳本會更改idm的UA設置,而有的腳本需要將idm更改為單線程下載。
2、開通網路網盤會員 如果多個腳本同時失效,並且其他人都能正常使用腳本下載文件,那很有可能是自己的賬號被網路官方拉黑了,也就是限速。
這種情況可以考慮充值一個月的網盤會員,會自動解封。
4. 怎樣編寫shell腳本實現統計一個小組的成績情況,統計信息包括:總分,平均分,最高分
#!/bin/bash
# 2013/07/01 sun
#功能說明:實現統計錄入學生成績的總人數,得出最高分,最低分,平均分,方差,標准方差,還有各個分數段的所佔百分比
echo "請輸入所有學生的成績,以空格隔開:"
read -a score_arr
#定義一個數組來存放用戶輸入的成績
sorted_arr=($(printf '%s\n' "${score_arr[@]}"|sort -n -r))
#錄入學生成績,並且是成績之間使用空格隔開
declare -i i b=0 c=0 d=0 e=0 f=0
#定義變數i來循環數組,依次讀出數組裡面的數據,定義五個初值為0的變數來存放每個分數段的人數
for (( i=0; $i<${#sorted_arr[@]}; i=$i+1 ))
#進行for循環,依次取出數組裡面的數據
do
#對每個取出來的數據進行判斷
case ${sorted_arr[i]} in
?|?\.*|[1-5]?|[1-5]?\.*)
#如果取出數組裡面的數據在60分以下
b=$(($b+1));;
#變數b自加1,進行統計數據
6?|6?\.*)
#如果取出數組裡面的數據在60分--69分之間
c=$(($c+1));;
#變數c自加1,進行統計數據
7?|7?\.*)
#如果取出數組裡面的數據在70分--79分之間
d=$(($d+1));;
#變數d自加1,進行統計數據
8?|8?\.*)
#如果取出數組裡面的數據在80分--89分之間
e=$(($e+1));;
#變數e自加1,進行統計數據
100|100\.0|9?|9?\.*)
#如果取出數組裡面的數據在90分--100分之間
f=$(($f+1));;
#變數f自加1,進行統計數據
*)
score_rank[i]="Not a Score";;
esac
done
#判斷結束
count=$(($b+$c+$d+$e+$f))
#算出總人數
declare -i j max min ave countall=0 u ua=0 ual=0 uall=0 fang
#定義變數j,最大值max,最小值min,平均數ave,所有人的分數之和countall
max=${sorted_arr[0]}
#獲取排序後的數組的第一個數,也就是最大數
j=$((${#sorted_arr[@]}-1))
#得到排序後的數組的最後的一個分數的下標
min=${sorted_arr[j]}
#獲取排序後的數組的最後一個數,也就是最小數
for (( j=0; $j<${#sorted_arr[@]}; j=$j+1 ))
#進行for循環,讓學生成績相加,算出學生成績的總分
do
countall=$countall+${sorted_arr[j]}
done
ave=$countall/$count
#算出平均成績
for (( j=0; $j<${#sorted_arr[@]}; j=$j+1 ))
#進行for循環,讓學生成績相加,算出學生成績的總分
do
ua=$(awk -v va=${sorted_arr[j]} -v vb=$ave 'BEGIN{printf "%2d" ,va-vb}')
#讓每一個數都減去平均數然後賦值於ua
ual=$(awk -v va=$ua -v vb=$ua 'BEGIN{printf "%2d" ,va*vb}')
#算得ua的平方
uall=$(awk -v va=$uall -v vb=$ual 'BEGIN{printf "%2d" ,va+vb}')
#算出它們的總合,也就是方差
done
u=$(awk -v va=$uall -v vb=$count 'BEGIN{printf "%2d" ,va/vb}')
#算出學生成績的平均分,並賦值於ave
#下面是計算每個分數段的百分數
countb=$(awk -v va=$b -v vb=$count 'BEGIN{printf "%2.2f%%" ,va*100/vb}')
#echo $countb
countc=$(awk -v va=$c -v vb=$count 'BEGIN{printf "%2.2f%%" ,va*100/vb}')
#echo $countc
countd=$(awk -v va=$d -v vb=$count 'BEGIN{printf "%2.2f%%" ,va*100/vb}')
#echo $countd
counte=$(awk -v va=$e -v vb=$count 'BEGIN{printf "%2.2f%%" ,va*100/vb}')
#echo $counte
countf=$(awk -v va=$f -v vb=$count 'BEGIN{printf "%2.2f%%" ,va*100/vb}')
#echo $countf
#輸出結果
echo "總人數 最高分 最低分 平均分 方差 "
echo "$count $max $min $ave $u "
echo "標准方差="
echo "scale=5;sqrt($u)" | bc
#算出標准方差
echo " 60分以下 60--69 70--79 80--89 90--100"
echo "人數" " $b $c $d $e $f"
echo "比例" "$countb $countc $countd $counte $countf"
5. 組態軟體國內那家做的好推薦幾個比較一下
國內組態軟體大一點的分為四家:紫金橋RealHistorian、亞控組態王KingScada、力控ForceControl7.2 SP1、傑控FaMe。主要分析他們幾個的優缺點,如下:
設備驅動:紫金橋RealHistorian常用硬體種類常用型號支持
亞控組態王KingScada種類非常多,支持大量硬體型號
力控ForceControl7.2 SP1種類比較多,支持常用驅動和部分匯流排;功能相對比較全(modbus驅動,可以控制起始地址,數據長度,校驗高低位互換!可以很容易實現非標設備鏈接!)
傑控FaMe主要集中在主要的幾家國外廠家和網關等相關設備范圍比較小
歷史存儲:紫金橋RealHistorian.周期和變化保存兩種方式
亞控組態王KingScada.無
力控ForceControl7.2 SP1.周期和變化保存兩種方式和數據插入模式(條件保存)
傑控FaMe.無
點類型:紫金橋RealHistorian.內置多種點類型(模擬點、數字點、組合點、設備運行點、運算點等)
亞控組態王KingScada.IO離散,IO長整型,IO整型,IO實型,IO雙精度浮點,IO字元串
力控ForceControl7.2 SP1.模擬、數字、累計、控制、運算、組合和雪崩過濾點等7種類型(建點那裡,可以批量點鏈接,不同節點下,點名可以重名)
傑控FaMe.無
關系庫通訊:紫金橋RealHistorian.支持多種關系資料庫,包括Oracle、sql Server、Access、mysql、sqlite。 支持一些國產的關系庫例如:人大金倉,達夢
亞控組態王KingScada.無
力控ForceControl7.2 SP1.通過ADO,可以和所有的關系型資料庫通信,但是配置比較繁瑣。具體沒測試。
傑控FaMe.通過ADO方式把數據存儲到關系庫主要是acess、sqlsever。
腳本系統:紫金橋RealHistorian.完整的腳本語言,提供大量預定義函數,提供各種控制語句,可實現十分復雜的功能,同時有多種智能提示,使用方便簡潔。
亞控組態王KingScada.完整的腳本語言,類VC,提供大量預定義函數,沒有中文注釋,需要對函數屬性比較熟悉才能熟練應用,使用較難
力控ForceControl7.2 SP1.無
傑控FaMe.直接內嵌的vb的腳本系統,腳本都是寫在統一界面,多處共用,但是開發需要有vb的基礎。
圖庫:紫金橋RealHistorian.為用戶提供幾千種具有立體效果的精美子圖,覆蓋各行各業,且可根據用戶需求,快速定製相關行業子圖。
亞控組態王KingScada.KingScada提供較多的立體圖形,覆蓋各行各業,用戶也可根據需求定製子圖,比較精美
力控ForceControl7.2 SP1.不精美,數量很多
傑控FaMe.無
HTML5:紫金橋RealHistorian.支持
亞控組態王KingScada.
力控ForceControl7.2 SP1.不支持
傑控FaMe.不支持
OPC Server組件:紫金橋RealHistorian.DA/UA
亞控組態王KingScada.DA
力控ForceControl7.2 SP1.支持DA(需要配置)
傑控FaMe.不支持
跨平台支持能力:紫金橋RealHistorian.支持常用的Windows系列操作系統、支持國產麒麟系列操作系統以及RedHat、Ubuntu、CentOS等多種Linux桌面操作系統和各種Linux嵌入式操作系統。除支持通用的Intel、AMD處理器,還支持龍芯、兆芯、飛騰、申威、眾志等國產處理器。
亞控組態王KingScada. 支持的操作系統語言版本:中文簡體、英文。支持的操作系統位數:32位、64位Windows Server 2008 R2 標准版、Windows Server 2012 R2 企業版、Windows Server 2016 R2 企業版、Windows 7 旗艦版、Windows 8 專業版、Windows 10
力控ForceControl7.2 SP1.只支持Windows系列操作系統
傑控FaMe.只支持Windows系列操作系統
嵌入式系統支持能力:紫金橋RealHistorian.系統採用可裁剪式架構,以及擁有良好的跨平台特性,能夠適應多種不同配置的嵌入式設備及操作系統(嵌入式Linux、VxWorks、WinCE等)
亞控組態王KingScada. 不支持
力控ForceControl7.2 SP1.不支持
傑控FaMe.不支持
單機容量:紫金橋RealHistorian.800萬點
亞控組態王KingScada.100W點
力控ForceControl7.2 SP1.最大案例大慶石油天然氣項目點數達40000點
傑控FaMe.不知道
數據轉儲:紫金橋RealHistorian.支持通過數據轉儲功能配置,將實時數據和歷史數據存儲到各種關系庫當中SQL Server、Access97-2000、Access2002-2003、Access2007、Oracle、Mysql。
亞控組態王KingScada.KingDataLogger主要實現從KingIOServer工程中讀取數據、緩存數據,並存儲至不同種類的資料庫、不同的表。目前支持的資料庫包括:工業庫KingHistorian、SQL Server、Access97-2000、Access2002-2003、Access2007、Oracle、Mysql
力控ForceControl7.2 SP1. 不支持
傑控FaMe. 不支持
希望對你有所幫助,通過數據分析得到你想要的
6. 急!用友U8誤刪UA_TASK 和 UA-TASKLOG怎麼恢復啊坐等高手
你是刪除了這兩個表嗎?
資料庫是哪個版本?2000還是2005?注意ua_tasklog是表,ua_task是視圖
在查詢分析器或Microsoft SQL Server Management Studio中運行下面兩個語句:
1、創建 ua_task:
USE [UFSystem]
GO
/****** 對象: View [dbo].[ua_Task] 腳本日期: 10/11/2013 15:54:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
---------------zhengyun增加欄位,修改索引--------------------------------
CREATE VIEW [dbo].[ua_Task]
AS
SELECT [cAcc_Id], [iYear], [cUser_Id], [cAuth_Id], [cStation], [cTaskId], [iLogId], [cSub_id], [cAppServer], [cAuthClassCode],[iBeginYear]
FROM [UFSystem].[dbo].[ua_Task_Common]
union
SELECT [cAcc_Id], [iYear], [cUser_Id], [cAuth_Id], [cStation], [cTaskId], [iLogId], [cSub_id], [cAppServer], [cAuthClassCode] ,[iBeginYear]
FROM [UFSystem].[dbo].[UA_Task_Special]
2、創建 ua_tasklog:
USE [UFSystem]
GO
/****** 對象: Table [dbo].[UA_TaskLog] 腳本日期: 10/11/2013 15:51:46 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[UA_TaskLog](
[cSub_Id] [nvarchar](2) COLLATE Chinese_PRC_CI_AS NULL,
[cSub_Name] [nvarchar](40) COLLATE Chinese_PRC_CI_AS NULL,
[cStation] [nvarchar](255) COLLATE Chinese_PRC_CI_AS NULL,
[dInTime] [datetime] NULL,
[cTaskId] [nvarchar](20) COLLATE Chinese_PRC_CI_AS NOT NULL,
[TaskState] [nvarchar](40) COLLATE Chinese_PRC_CI_AS NULL,
[cAppServer] [nvarchar](80) COLLATE Chinese_PRC_CI_AS NULL,
[uuid] [nvarchar](40) COLLATE Chinese_PRC_CI_AS NULL,
[cLSSubId] [nvarchar](4) COLLATE Chinese_PRC_CI_AS NULL,
[cStationSerial] [nvarchar](255) COLLATE Chinese_PRC_CI_AS NULL,
CONSTRAINT [aaaaaUA_TaskLog_PK] PRIMARY KEY NONCLUSTERED
(
[cTaskId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
EXEC sys.sp_bindefault @defname=N'[dbo].[UA_TaskLog_TaskState_D]', @objname=N'[dbo].[UA_TaskLog].[TaskState]' , @futureonly='futureonly'
給你現導的,純手打。
求選
7. via瀏覽器如何使用腳本
腳本如下:
設置選項進入腳本選項即可。首先進入Via,點擊「三」按鈕;接著點擊「設置」,進入設置頁面,點擊「腳本」;打開腳本頁面,點擊右上角「+」按鈕即可添加腳本。
簡介:
Via瀏覽器是一款安卓平台瀏覽器。該瀏覽器採用簡潔的界面設計,提高搜索框權重,避免用戶被其他新聞等信息干擾,讓瀏覽器回歸搜索與瀏覽的本質,以提高效率。
進階:自定義瀏覽器標識ua;廣告標記攔截;下載插件;查看網頁源碼;資源嗅探;導入導出書簽;雲同步;隱私防追蹤;保存網頁;離線網頁;翻譯網頁;網頁內查找;有圖/無圖模式。
8. 程序開發中模塊開發什麼意思呢
模塊就是根據開發內容劃分,比如會員模塊,購物模塊,新聞模塊,廣告模塊
在交互模式下, Lu a 不斷的顯示提示符,並等待下一行輸入。 一旦讀到一行, 首先試著把這行解釋為一個表達式。 如果成功解釋,就列印表達式的值。 否則,將這行解釋為語句。 如果你寫了一行未完成的語句, 解釋器會用一個不同的提示符來等待你寫完。
當腳本中出現了未保護的錯誤, 解釋器向標准錯誤流報告錯誤。 如果錯誤對象並非一個字元串,但是卻有元方法 __tostring 的話, 解釋器會調用這個元方法生成最終的消息。 否則,解釋器將錯誤對象轉換為一個字元串,並把棧回溯信息加在前面。
如果正常結束運行, 解釋器會關閉主 L ua 狀態機 ( l。a_close)。 腳本可以通過調用 os.exit 來結束,以迴避這個步驟。
為了讓 L ua 可以用於 Unix 系統的腳本解釋器。 獨立版解釋器會忽略代碼塊的以 # 打頭的第一行。 因此,Lu a 腳本可以通過 chmod +x 以及 #! 形式變成一個可執行文件。 類似這樣
(當然, Lu a 解釋器的位置對於你的機器來說可能不一樣。 如果 lu a 在你的 PATH 中, 寫成
這里我們列出了把程序從 Lua 5.2 遷移到 Lua 5.3 會碰到的不兼容的地方。 你可以在編譯 Lua 時定義一些恰當的選項(), 來迴避一些不兼容性。 然而,這些兼容選項以後會移除。
Lua 的版本更替總是會修改一些 C API 並涉及源代碼的改變。 例如一些常量的數字值,用宏來實現一些函數。 因此,你不能假設在不同的 Lua 版本間可以做到二進制兼容。 當你使用新版時,一定要將使用了 Lu a API 的客戶程序重新編譯。
同樣,Lu a 版本更替還會改變預編譯代碼塊的內部呈現方式; 在不同的 Lu a 版本間,預編譯代碼塊不兼容。
官方發布版的標准路徑也可能隨版本變化。
Lua 5.2 到 Lua 5.3 最大的變化是引入了數字的整數子類型。 雖然這個變化不會影響「一般」計算, 但一些計算 (主要是涉及溢出的) 會得到不同的結果。
你可以通過把數字都強制轉換為浮點數來消除差異 (在 Lu a 5.2 中,所有的數字都是浮點數)。 比如你可以將所有的常量都以 .0 結尾, 或是使用 x = x + 0.0 來轉換一個變數。 (這條建議僅用於偶爾快速解決一些不兼容問題; 這不是一條好的編程准則。 好好寫程序的話,你應該在需要使用浮點數的地方用浮點數, 需要整數的地方用整數。)
把浮點數轉為字元串的地方,現在都對等於整數的浮點數加了 .0 後綴。 (例如,浮點數 2.0 會被列印成 2.0, 而不是 2。) 如果你需要定製數字的格式,就必須顯式的格式化它們。
(准確說這個不是兼容性問題, 因為 Lua 並沒有規定數字如何格式化成字元串, 但一些程序假定遵循某種特別的格式。)
分代垃圾收集器沒有了。 (它是 Lu a 5.2 中的一個試驗性特性。)
9. bat腳本,用IBM ITM監控軟體的UA調用,在windows2008上可用,在windowsXP上不能用
額……我胡亂猜的 錯了別介意
你這個腳本是用jit2Clientfor命令從MYSQL里篩選制定數據對吧?
如果是 那麼你可以在XP下手動執行這個命令(帶參數)看看報錯信息
同時可以逐漸減少參數 根據報錯信息分析哪個參數有問題
你的資料庫在XP本地么? 如果不是 也有可能是路徑問題?