年来,前端技术日新月异,前端已经不仅仅是网页,更多的开始由狭义向广义发展。
先后涌现出了具备后端能力的node,具备移动开发能力的react native,具备游戏渲染能力的cocos2d-js,以及iOS上的热修复技术JSPatch等等新技术。
咋一看,几乎各个端都被JavaScript攻陷,大有一统江湖之势。
究竟,JavaScript如何做到上天入地无所不能?JavaScript真的能一统江湖吗?
乱世出英雄:JavaScript的诞生故事要从JavaScript的由来说起。
高能瞎扯淡版,正经脸的同学可以忽略
有人的地方就有江湖,有江湖的地方就有纷争。
故事要从当年的浏览器之战说起。
时间回到1994年,
(→ 那时候我还是个宝宝~ #天真脸#)
景兄弟横空出世,并自带神器网景导航,战斗力爆表,势如劈竹,瞬时间威震天下。
一出世就武装到牙齿,武力值这么高还自带兵器,这个科学吗?
港真,我也觉得不科学,也许跟熊孩子哪吒、女汉子雅典娜是一个品种吧?
这一切北方的老前辈微软大湿,都看在眼里,不甘天下尽归景兄弟这个初出茅庐的毛孩子,大湿积淀多年,潜心修炼一年,终于带着大杀器IE 1.0出关了,誓于景兄弟争个高低。
自此景兄弟的网景导航 VS 微软大湿的IE 的军备战争开始。
景兄弟仔细掂量,微软大湿财大气粗,内功深厚,臣妾实在是办不到啊啊啊啊啊啊。
景兄弟紧急召集门人商议对策,有一门人曰:”以我们微薄之力硬磕,是万万使不得的。如今我们,一是宜施行合纵之策,抱大腿,组成联盟!二是避其锋芒,出奇招致胜。“
于是景兄弟依照此策略,一方面找到了当时德高为重的另一位前辈SUN,组成了开发者联盟。
(微软大湿:握草,联盟都粗来了,那我是不是得搞个部落?)
另一方面,景兄弟找到了锻造大师布兰登,请布大师帮忙升级兵器网景导航,大师就是大师,不费吹灰之力就完成了强化升级,然而布大师突发奇想,本来这是近距离攻击兵器,要是有多一个远距离攻击的能力那岂不是更好?Just do it. 想罢大师就加了一个远距离攻击的feature。于是有了自带远距离攻击能力的网景导航2.0。景兄弟一看这么流弊心里甚是欢喜,不过远距离攻击的技能叫做LiveScript,感觉不是特别Fashion。特然想到这不是跟SUN前辈联盟嘛,SUN家的Java正是独霸武林之时。不如把名字改成跟Java有关,蹭一把东风,蹭点光环。一拍脑袋,JavaScript!!!众门人一听:”好好好,JavaScript 流弊炫酷吊炸天!“
果然第一节下半场,景兄弟携强化过的网景导航2.0 战个痛快,那是杠杠的!人家一问,你咋还能远程攻击,你这个远程攻击用的是啥?答曰:JavaScript。“JavaScript,一定是跟SUN家Java是一个系列产品,一定很流弊!”#光环加成,各种膜拜脸#
微软大湿亏了一场,痛定思痛,也要搞远程攻击功能,果然不久,就祭出了同样带有远程攻击能力的IE 3.0,鉴于景兄弟的远程攻击叫做JavaScript,J开头的感觉应该比较流弊,所以微软大湿的叫做JScript。
然后战争就从地面贴身肉搏战,开始逐步升级到了远距离核战争。
正所谓,城门失火,殃及池鱼。这么打下去苦逼的是搬砖的页面仔,就是我这种,到处都是雷区,无处下脚。
最后到了1997年,“联合国安理会秘书长”艾玛(ECMA)出来调停,多方签署了“核不扩散条约”,约束各种远程攻击武器的使用,这才走上了正轨。
1995年SUN开发了Java技术,这是第一个通用软件平台。Java拥有跨平台、面向对象、泛型编程的特性,广泛应用于企业级Web应用开发和移动应用开发。Java也伴随着互联网的迅猛发展而发展,逐渐成为重要的网络编程语言。名噪一时。
1994年Netscape公司成立,并推出了自己的浏览器的免费版本 Netscape Navigator,很快就占有了浏览器市场。到了 1995 年,微软公司开始加入,并很快发布了自己的 Internet Explorer 1.0。
1995年,当时在Netscape就职的Brendan Eich(布兰登·艾克),正为Netscape Navigator 2.0浏览器开发的一门名为LiveScript的脚本语言,后来Netscape与Sun Microsystems组成的开发联盟,为了让这门语言搭上Java这个编程语言“热词”,将其临时改名为“JavaScript”,日后这成为大众对这门语言有诸多误解的原因之一。
JavaScript最初受Java启发而开始设计的,目的之一就是“看上去像Java”,因此语法上有类似之处,一些名称和命名规范也借自Java。但JavaScript的主要设计原则源自Self和Scheme。JavaScript与Java名称上的近似,是当时Netscape为了营销考虑与SUN达成协议的结果。
==> 所以,JavaScript和Java其实没有半毛钱关系。
JavaScript推出后在浏览器上大获成功,微软在不久后就为Internet Explorer 3.0浏览器推出了JScript,以与处于市场领导地位的Netscape产品同台竞争。JScript也是一种JavaScript实现,这两个
JavaScript语言版本在浏览器端共存意味着语言标准化的缺失,对这门语言进行标准化被提上了日程,在1997年,由Netscape、SUN、微软、宝蓝等公司组织及个人组成的技术委员会在ECMA(欧洲计算机制造商协会)确定定义了一种名叫ECMAScript的新脚本语言标准,规范名为ECMA-262。JavaScript成为了ECMAScript的实现之一。ECMA-262 第五版,即是ES5。
==> ECMA-262,包括ES5, ES6等是一个标准,JavaScript是ECMAScript的一个实现。
完整的JavaScript实现应该包含三个部分:
在网景导航2.0和IE 3.0出现之后的几年间,网景和微软公司不停的发布新版本的浏览器,支持更多的新功能。自此拉开了浏览器之战的序幕。这场浏览器之战到现在还在继续,以下一张图看清楚过程。
从浏览器之战可以看出,各家浏览器比拼的大致两个方面视觉体验(渲染排版)和速度(脚本运行)。
==> 所以一个完整的浏览器组成,至少包含两个部分:
补充一个市面常见浏览器的内核和JavaScript引擎搭配:
其他JavaScript引擎,Rhino,由Mozilla基金会管理,开放源代码,完全以Java编写,可以看做SpiderMonkey的Java版。
注意:webkit不单单只是一个排版引擎,webkit = 排版引擎 + JavaScript引擎。
==> 所以,JavaScript是动态语言,它的运行都是基于JavaScript引擎,引擎大都是由静态语言实现C++、Java、and so on。JavaScript的能力也是由引擎赋予。不管是浏览器环境中是window,亦或是node环境中的process,均是由引擎提供。
(番外:Mozilla的人不知道为啥特别喜欢猴子,经常以猴子命名技术,所以看到带Monkey的,十有八九估计是他们搞的。)
在浏览器环境中,DOM、BOM、window对象、setTimeout/setInterval,alert,console等方法均不是JavaScript自身具备的能力,而是浏览器native实现,然后通过JavaScript引擎注入到JS运行的全局上下文中,供JS使用。
鉴别方式,在调试器console中打出来,带有[native code]的即是:
讲道理:
JavaScript运行 → 依赖于JavaScript引擎 ← 浏览器集成了JavaScript引擎,同时通过JavaScript引擎注入native代码工JS脚本使用
发散一下思维,只要有JavaScript引擎,就能运行JS脚本,不管有没有浏览器!只是缺少浏览器提供的alert,window等方法。
既然浏览器可以往JavaScript引擎中注入代码,赋予JS脚本在网页中特殊的能力,同理我们可以自己集成JavaScript引擎,自己定义自己的方法往JavaScript引擎中注入,赋予JS更多更强的自定义能力!
注入的关键是:值类型相互对应,Obj映射class的一个实例,function映射一个句柄或者引用
JavaScript内部,所有数字都是以64位浮点数形式储存,即使整数也是如此
这就是说,在JavaScript语言的底层,根本没有整数,所有数字都是小数(64位浮点数)。容易造成混淆的是,某些运算只有整数才能完成,此时JavaScript会自动把64位浮点数,转成32位整数,然后再进行运算。由于浮点数不是精确的值,所以涉及小数的比较和运算要特别小心。尽量避免使用JavaScript做精准计算和密集计算。
根据国际标准IEEE 754,JavaScript浮点数的64个二进制位,从最左边开始,是这样组成的。
第1位:符号位,0表示正数,1表示负数
第2位到第12位:储存指数部分
第13位到第64位:储存小数部分(即有效数字)
符号位决定了一个数的正负,指数部分决定了数值的大小,小数部分决定了数值的精度。
IEEE 754规定,有效数字第一位默认总是1,不保存在64位浮点数之中。也就是说,有效数字总是1.xx…xx的形式,其中xx..xx的部分保存在64位浮点数之中,最长可能为52位。因此,JavaScript提供的有效数字最长为53个二进制位(64位浮点的后52位+有效数字第一位的1)。
内部表现公式:(-1)^符号位 1.xx…xx 2^指数位
精度最多只能到53个二进制位,这意味着,绝对值小于2的53次方的整数,即-(253-1)到253-1,都可以精确表示。
而大部分的后端语言,C++、Java、Python等的long型都是可以支持到64位,因此long型数据从后端语言传给JavaScript会发生低位截断。遇到这种情况一般使用String处理,如需要在JavaScript中做long型计算,需要自行实现计算器。
有了自行往JavaScript引擎中注入的想法,接下来就是分析可行性。
大部分是JavaScript引擎是使用C++编写,如果自己的程序使用的是C++可以很方便的进行注入,如果是OC,可以使用OC和C++混编的形式。
其他语言怎么破?
要在一门静态语言上与动态语言JavaScript相互调用,最便捷的方式是找到一个这门语言实现的JavaScript引擎(开源),直接进行集成,注入。如果没有,则需要使用多一层桥接,把这门语言的接口暴露给C++,再由C++实现的JavaScript引擎将接口注入供JavaScript使用。
服务端集成思路&实践:
我们都知道nodeJS,但是nodeJS的运行依赖于Google的V8 引擎,V8是C++实现,底层使用C++实现底层功能,比如网络,数据库IO,对外暴露一个构造器接口注入到上下文中,注意此处暴露的只是一个构造器接口而不是一个创建完的实例。然后实现了一个require的hook函数。当使用require加载一个JS模块时,跟网页中使用AMD 的require并无异样,当使用require加载系统库,既是C++的模块时,会调用暴露出来的构造器接口,得到一个实例对象。不管是装载JS模块还是装载C++模块,得到的都可以看做是一个Module Object,node会将装载完的模块缓存到binding_cache中,下次在别处的代码中使用require装载模块时,就会先去binding_cache中查找,如果找到了则返回该module object,如果没找到再执行上面的装载流程。
这就是node的基本原理:C++封装底层操作,通过V8注入,使得JS脚本有网络和IO能力
以上说到的几个都是C++层面的应用,那么经典的Java怎么玩?是不是Java就必须是静态语言的玩法,没有办法像C++之类的,可以使用JS的动态特性?
当然不是。这个时候,我们需要说起前面介绍过的一个JS引擎 Rhino,Rhino是完全由Java编写,可想而知,Rhino几乎就是为Java应用而生的。
用法是这样:
首先在我们的Java应用中集成Rhino;
所有的IO操作,网络操作等,都封装成service,并提供增删改查,setter && getter等多种方法
通过spring,把这些service bean注入到Rhino中;
把业务逻辑写到JS代码中,JS代码调用多个已注入的Java service处理业务逻辑,拼装数据返回!
好处:修改业务逻辑不需要修改Java代码,也就是不需要重新编译和部署,只需要刷新下跑在Rhino中的JS代码即可。以往Java应用的一个痛点是部署,需要重新编译,打包,部署重启服务器,现在以这种形式开发,可以达到服务端的热更新和热部署。既可以享有Java服务的稳定性和可靠性,又可以享有JS的灵活性。
这种技术和用法在差不多十年前就有过,前EMC的工程师基于EMC著名的商业产品Documentum,设计了一套Java开源的中小企业CMS系统Alfresco,在该系统中实现了这种技术,这种技术基于spring,叫做spring-surf,做了一个胶水层。可以看做小十年前的node吧。
Demo,使用spring-surf框架的系统中一个webscript模块
categorynode.get.xml定义URL拦截器和权限控制;
.get指明是处理GET请求,RESTful;
在categorynode.get.js中调用已注入的Java Bean处理业务逻辑;
若为网页请求返回.html.ftl,若为Ajax,返回.json.ftl;
(此处配套使用的是FreeMarker模板引擎)
==> categorynode.get.desc.xml
==> categorynode.get.js
==> categorynode.get.html.ftl
==> categorynode.get.json.ftl
React Native目前也是异常火爆,RN程序的运行依赖于Facebook的RN框架。在iOS、Android的模拟器或是真机上,React Native使用的是JavaScriptCore引擎,也就是Safari所使用的JavaScript引擎。但是在iOS上JavaScriptCore并没有使用即时编译技术(JIT),因为在iOS中应用无权拥有可写可执行的内存页(因而无法动态生成代码),在安卓上,理论上是可以使用的。JavaScriptCore引擎也是使用C++编写,在iOS和安卓中,JavaScriptCore都做了一层封装,可以无须关心引擎和系统桥接的那一层。iOS/Android系统通过JavaScriptCore引擎将定制好的各种原生组件注入,如:listview,text等。
cocos2dx是游戏开发中非常常用的游戏渲染引擎,有一系列的产品,如:cocos2dx(C++),cocos2d-lua(lua), cocos2d-js(JavaScript)等多个产品。其中最新退出的是cocos2dx的JS版本的cocos2d-js,编写游戏渲染特效代码相比于C++和lua非常方便。对于做需要经常更新的渲染场景,C++是静态语言,每次修改都需要重新编译才能运行,显然是不合适的。自然也就想到了脚本语言,lua和js,两者有些类似,都是动态语言,只需要集成一个运行引擎,提供一个运行的容器即可运行,同时通过引擎注入底层方法供脚本调用即可。lua好处是精简,语法精简,引擎页很小很精简,所以不可避免的代码量会比js多,同时学习成本比较高。js的好处是有ECMAScrtpt的核心,语法比较丰富,同时有支持一些高级属性。在cocos2d-js中,cocos2dx(C++)集成了SpiderMonkey(C++)作为JS运行引擎,中间做了一个胶水层既是JS Binding,通过引擎注入了一个cc的全局对象,映射的是底层C++的一个单例C++实例。表面上写的是JS代码,实际上操作的是底层的C++。cocos2d-js是代码可以运行在多种环境中,当运行的网页环境中时,使用的是cocos2d-html5引擎,底层操作的是canvas;当运行在客户端上时,使用的是cocos2dx引擎,底层操作的是C++,再由C++去操控openGL做绘制和渲染。提供相同的API,对开发者几乎是透明无差异的,开发者只需要关注实现效果即可。达到一套代码,多端运行(网页端,客户端)。
JSPatch是目前比较流行的iOS上的热修复技术,JSPatch 能做到通过 JS 调用和改写 OC 方法最根本的原因是 Objective-C 是动态语言,OC 上所有方法的调用/类的生成都通过 Objective-C Runtime 在运行时进行,我们可以通过类名/方法名反射得到相应的类和方法。JSPatch 的基本原理就是:JS 传递字符串给 OC,OC 通过 Runtime 接口调用和替换 OC 方法。
关键技术之一是 JS 和 OC 之间的消息互传。JSPatch里包含了,一个JS引擎JavaScriptCore(Safari,React Native用的同款)。用到了 JavaScriptCore 的接口,OC 端在启动 JSPatch 引擎时会创建一个 JSContext 实例,JSContext 是 JS 代码的执行环境,可以给 JSContext 添加方法,JS 就可以直接调用这个方法。本质上就是通过JavaScriptCore引擎注入,暴露OC的方法供JS调用来实现动态修改OC的反射。
Demo,iOS热更新,热修复:
集成JavaScriptCore引擎;
通过引擎,桥接JS和OC;
通过JS修改OC反射。
详细的JSPatch技术介绍请移步:https://github.com/bang590/JSPatch/wiki
关于JavaScript引擎:
在iOS 或 android 上能够运行的JavaScript 引擎有4个:JavaScriptCore,SpiderMonkey,V8,Rhino。下面这个表格展示各个引擎在iOS 和 Android 的兼容性。
因为iOS平台不支持JIT即时编译,而V8只有JIT模式,所以V8无法在iOS平台使用(越狱设备除外,想体验iOS JIT的同学可以自行越狱)。
所以,目前可以做到横跨iOS和Android双平台的JS引擎,只有两款,即是SpiderMonkey和JavaScriptCore。
JavaScript引擎会受很多东西影响,比如交叉编译器的版本、引擎的版本和操作系统的种类等。
至于如何选择,可以参考:《Part I: How to Choose a JavaScript Engine for iOS and Android Development》
至此,JavaScript从立足于前端,到征战全端的逆袭之路,可以总结为“携引擎以令天下”。
不足之处,还请各位看官轻拍~
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 从入门到源码》
源引擎天生具有分享精神,近日,Cocos 2d-JS中文版API文档正式上线。为满足广大国内开发者的阅读习惯,便于大家能更好地了解引擎架构,学习关键技术点,Cocos 2d-JS力邀了众多开发者参与此次翻译工作。
据悉,该API文档基于Cocos 2d-JS 3.2rc0版本,开发者可以在文档中浏览Cocos 2d-JS的所有类、函数以及使用方法,快速检索学习及开发过程中所需要的方法。
HTML5技术是近两年来移动开发世界里的新贵。原来应用的开发者可能需要花费非常大的力气才能达到HTML5游戏开发的效率,需要不断地重复编码、调试、运行;然而HTML5手机应用的最大优势就是可以在网页上直接调试和修改,同时,当下市面上的主流手机浏览器都具备支持HTML5的能力让基于HTML5的移动轻游戏迅速蹿红,即点即玩又能迅速传播正在成为行业标杆。
Cocos 2d-JS是Cocos 2d-x的JavaScript版本,融合了HTML5技术和Cocos 2d-x JavaScript Binding(JSB),支持Cocos 2d-x的所有核心特性并提供更简单易用的JavaScript风格API,能帮助开发者方便地使用JavaScript语言进行游戏开发,快速构建原型进行验证,并能让游戏跑在所有支持HTML5规范的浏览器上。
HTML5游戏越来越流行,在移动游戏行业中的比重也是越来越大,市场上已经有相当多的休闲、社交类游戏基于HTML5规范开发。Cocos 2d-JS带来了易学易用的Cocos 2d API到HTML5游戏开发领域,在保证高效开发的前提下,也秉承了HTML5游戏实时更新、即点即玩的特性,能给产品带来更高的用户转换率,更强的市场竞争力。
基于Cocos 2d-JS研发的千万级明星游戏
同时,Cocos 2d-JS是跨全平台的游戏引擎,完美支持“一套代码,全平台运行”,所以开发者也可以采用JavaScript语言逐鹿原生游戏市场。该技术方案天然支持在线资源、脚本热更新,高性能、高效率,能完美支持各种复杂炫酷的游戏效果。目前已有多款如《变形金刚:崛起》、《三国杀传奇》等基于Cocos 2d-JS开发的产品成功跻身千万级明星游戏之列。
与此同时,DeNA另一款采用Cocos 2d-JS研发的正版精品手游《航海王 起航》也和广大玩家见面了。经典的主题曲,熟悉的原班声优,热血的冒险世界,这款作品在上线后的短短两小时就攀至iOS付费榜No.2,不负众多海贼粉丝、重度游戏玩家的期望。
Cocos 2d-JS力邀众多开发者参与此次翻译工作,中文版API文档旨在帮助到所有国内使用Cocos 2d-JS的开发者,在文档中,开发者可以检索到Cocos 2d-JS的所有类、函数以及使用方法,在学习和开发过程中节省大量的时间,进一步减少成本,更加畅快地享受Cocos 2d-JS带来的高效率高性能、全平台覆盖的开发体验。
如果说一款开源的引擎是一片湖泊,那么所有使用引擎的开发者就是汇向湖泊的涓涓细流,也是湖泊里的鱼,既是受益者,也是奉献者。Cocos 2d-JS中文版API文档得到了众多开发者的无私的奉献与支持,Cocos也会不断努力进取,为大家提供更强大更易用的引擎和工具,助力开发者斩获市场。
感谢为此文档做出贡献的开发者:
http://cn.cocos2d-x.org/doc/jsdoc/volunteerlist.html
戏引擎是开发商研发游戏时必须的工具,每一款引擎的运用都关乎自家游戏未来的销量,所以游戏商们对引擎的选择也非常重视。现在,手游、页游等新兴平台的表现又非常强势,所以选择正确的游戏引擎变得尤为重要。
一、Unity 3D
Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。
代表作游戏:
二、虚幻引擎
虚幻引擎的设计目的非常明确,每个方面都具有较高的易用性,尤其侧重于数据生成和程序编写的方面,这样,美工只需要程序员的很少量的协助,就能尽可能多地开发游戏的数据资源,并且这个过程是在完全可视化环境中完成的,实际操作非常便利。
代表作游戏:
三、Cry Engine 3
Cry Engine3,是德国的CRYTEK公司出品一款对应最 新技术DirectX11的游戏引擎。2001年引入的这个“沙盒”是全球首款”所见即所玩”(WYSIWYP)游戏编辑器,现已发展到第三代,WYSIWYP功能将提升到一个全新层次,并扩展到了PS3和X360平台上,允许实时创作跨平台游戏,另外工具包内的创作工具和开发效率也都得到了全面增强。
代表作游戏:
四、白鹭(Egret)
Egret是一套完整的HTML5游戏开发解决方案。Egret中包含多个工具以及项目。Egret Engine是一个基于TypeScript语言开发的HTML5游戏引擎,该项目在BSD许可证下发布。用Egret Engine开发的游戏可发布为HTML5版本,运行于浏览器之中。同时,也可以发布为iOS、Android和WindowsPhone原生程序。
五、Cocos 2D
Cocos2d-x是一个开源的移动2D游戏框架,MIT许可证下发布的。这是一个C++ Cocos2d-iPhone项目的版本。Cocos2d-X发展的重点是围绕Cocos2d跨平台,Cocos2d-x提供的框架。手机游戏,可以写在C++或者Lua中,使用API是Cocos2d-iPhone完全兼。Cocos2d-x项目可以很容易地建立和运行在iOS,Android,黑莓Blackberry等操作系统中。
代表作游戏:
以上几款游戏引擎是国内一些时下比较流行的游戏引擎。在当下时代,随着全民移动手游的发展趋势,感觉以后Unity3D游戏引擎,以后发展会更好一点。纯属个人观点,不喜勿喷。
更多有趣好玩的消息,关注好玩学院!
*请认真填写需求信息,我们会在24小时内与您取得联系。