【cocos2d-x从c++到js】20:脚本语言风格的JS代码

简介:

最近听说Cocos2d JS官方在组织写新的代码例子。并且林顺同学在开会时说,Cocos2d JS接口将回归JS风格,成员变量访问方式用“.”,以及初始化时用对象字面量{}。非常不错啊。


如果之前是Cocos2d-x的C++程序员,在使用Cocos2d JS时很容易沿用C++的思路来写脚本。这种方式不容易发挥出脚本语言的快速开发优势。


在Cocos2d-x 的例子代码中有一些写法,尤其是在Test中,有许多代码是按照C++例子原样翻译过来的。里面应用了很多继承与组合等代码组织方式。并且,很多静态强类型语言的写法(类型强迫症),在脚本语言中对于开发速度是有很大影响的。


一、继承VS动态添加成员


继承,是一种最重量级的代码复用方式(他有自己的优势但是也有非常多的副作用)。但是问题在于,很多编辑器和运行库是既不支持协变又不支持各种动态绑定。这种情况下会让你的继承代码毫无作用。你只能选择组合,而组合差不多是一种最罗嗦的代码复用方式。他会很大程度抵消你的脚本语言开发速度优势。从这种情况看来CocosBuilder的设计无疑比CocoStudio要先进许多。


那么怎么做呢?因为脚本语言的优势可以在运行时动态给一个实例添加成员。 (Dynamic addition of methods and attributes to instances.)使用这种特性就可以跳过繁琐的继承+组合复用方式来构建代码。并且Cocos2d-x作为游戏引擎,因为存在UI等显示系统,也就是说存在一个全局节点树,可以用来递归遍历所有显示对象,使用类型判定然后直接调用相应的扩展函数直接在对象实例上进行扩展。


上面说的是指基于Cocos2d JS的二次开发代码的使用方法。在编写功能代码时也可以应用这种特性。


这么做的坏处是会破坏JS内部的类型系统(构造器与对象行为不匹配)。如果库的编写者和使用者没有充分沟通,可能会遇到无法理解的代码。让对象行为变得不可控,因为JS本身就是动态弱类型的。所以一定要严格限制功能代码中被扩展的对象的作用范围和使用范围,必要时使用文档规范,避免其他人接手莫名其妙的代码。


而对于自带运行库的编辑器来说,还有第二种选择——直接扩展插件。这是完全按照强类型的路子走了。


二、装载时执行OR装载时注册启动时初始化


代码在加载时可以执行,这是脚本语言的又一个特色。因此我们可以在代码文件被装载时自动做很多初始化工作。


但是这么搞也是存在一定问题的,如果初始化代码散落在不同的文件中,对debug是不利的。需要在多个调用点去来回查找。


不过凡事都有例外,如果你把很多代码当成资源加载,就不存在这种问题。比如,加载一些AI脚本、动画脚本、UI脚本的时候,就不存在这种问题。因为这些代码的接口规范都很统一,而且一定会有一个外部装载机制和管理机制。先通过读取文件将启动函数绑定好,再统一启动。


三、具名索引And有限状态机FSM


访问一个对象的成员,可以用[]内嵌名字(具名索引access attribute by name),也可以用.后面加名字。我建议动态获得的成员名进行访问时使用前一种方式,普通的成员访问时候使用后一种,以示区别。


尤其是通过[]内嵌名字方式,可以直接调用函数这种方式,可以非常好的同游戏中的各种状态机制和脚本指令结合。比状态模式(基于对象和接口)与状态变量(基于switch-case)要简便许多。


四、文件访问域And模块化


JavaScript的函数级作用域其实是很讨厌的。有几条原因:

1.一不小心很容易就污染了全局变量和全局函数

2.因为1的原因如果你选择对象构造方式来避免污染全局作用域又会遇到另外一个问题就是this。这个this不但罗嗦,每句都得写。还常常乱变,例如:bind callback的时候,在回调函数启动的时候,你常常无法确定当前this到底是哪个对象。(当然,在JS中也有一种叫bind this的技术,但有句话是:与其每次都解决问题,不如根本没问题)


Coffee是用闭包方式构造一个“文件访问域”的,还有很多库也有这种功能。这可以让你:

1.省掉写this

2.不会污染全局


当然如果你能支持module require还可以做更多的功能模块化开发(这对于前后端统一JS开发也很有好处)。官方介于闭包的性能和兼容性问题(都要考虑浏览器),应该不会添加CommonJS支持。


五、匿名回调函数


在bind callback时,直接通过匿名函数方式打入回调函数,是一种不错的方式,能够少写很多代码。


但是很多时候,如果遇到复杂流程控制,多种状态切换时,这种原地展开的callback,就会让代码可读性和错误查找变得困难起来,并且由于这种写法的上下文非常隐晦,还会引入this问题。


对于简单的UI显示控制,纯显示效果调用,匿名函数这种方式还是可以的。但是如果遇到复杂流程,并且牵扯到上下文,逻辑控制,函数复用,还是老老实实写实现,然后再bind callback时bind 函数比较好一点。



最后


都说JS的代码编写很多时候是基于函数的。卡哥的名言——“很多时候需要的仅仅是一个函数”。


写功能代码的时候。相对于OO,很多时候,你需要的是一个有用的对象,而不是类。对于类使用,在倾向于封装代码和类型约定(这个便于review和debug),但是如果说为了复用,明显有点太扯了(离需求太近,专门定制化的类,复用一定成问题)。当然关心代码质量和复用是好事,但是搞成项目改得精疲力尽就得不偿失了。



 本文转自 老G 51CTO博客,原文链接:http://blog.51cto.com/goldlion/1388618,如需转载请自行联系原作者



相关文章
|
2月前
|
JavaScript 前端开发 算法
流量分发代码实战|学会用JS控制用户访问路径
流量分发工具(Traffic Distributor),又称跳转器或负载均衡器,可通过JavaScript按预设规则将用户随机引导至不同网站,适用于SEO优化、广告投放、A/B测试等场景。本文分享一段不到百行的JS代码,实现智能、隐蔽的流量控制,并附完整示例与算法解析。
79 1
|
3月前
|
JavaScript 前端开发
怀孕b超单子在线制作,p图一键生成怀孕,JS代码装逼娱乐
模拟B超单的视觉效果,包含随机生成的胎儿图像、医疗文本信息和医院标志。请注意这仅用于前端开发学习
|
3月前
|
JavaScript
JS代码的一些常用优化写法
JS代码的一些常用优化写法
66 0
|
3月前
|
C++
爱心代码 C++
这段C++代码使用EasyX图形库生成动态爱心图案。程序通过数学公式绘制爱心形状,并以帧动画形式呈现渐变效果。运行时需安装EasyX库,教程链接:http://【EasyX图形库的安装和使用】https://www.bilibili.com/video/BV1Xv4y1p7z1。代码中定义了屏幕尺寸、颜色数组等参数,利用随机数与数学函数生成动态点位,模拟爱心扩散与收缩动画,最终实现流畅的视觉效果。
157 0
|
5月前
|
存储 JavaScript 前端开发
在NodeJS中使用npm包进行JS代码的混淆加密
总的来说,使用“javascript-obfuscator”包可以帮助我们在Node.js中轻松地混淆JavaScript代码。通过合理的配置,我们可以使混淆后的代码更难以理解,从而提高代码的保密性。
411 9
|
6月前
|
前端开发 JavaScript
【Javascript系列】Terser除了压缩代码之外,还有优化代码的功能
Terser 是一款广泛应用于前端开发的 JavaScript 解析器和压缩工具,常被视为 Uglify-es 的替代品。它不仅能高效压缩代码体积,还能优化代码逻辑,提升可靠性。例如,在调试中发现,Terser 压缩后的代码对删除功能确认框逻辑进行了优化。常用参数包括 `compress`(启用压缩)、`mangle`(变量名混淆)和 `output`(输出配置)。更多高级用法可参考官方文档。
419 11
|
6月前
|
JavaScript 前端开发 算法
JavaScript 中通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能,JS中排序算法的使用详解(附实际应用代码)
Array.sort() 是一个功能强大的方法,通过自定义的比较函数,可以处理各种复杂的排序逻辑。无论是简单的数字排序,还是多字段、嵌套对象、分组排序等高级应用,Array.sort() 都能胜任。同时,通过性能优化技巧(如映射排序)和结合其他数组方法(如 reduce),Array.sort() 可以用来实现高效的数据处理逻辑。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
6月前
|
JavaScript 前端开发 API
JavaScript中通过array.map()实现数据转换、创建派生数组、异步数据流处理、复杂API请求、DOM操作、搜索和过滤等,array.map()的使用详解(附实际应用代码)
array.map()可以用来数据转换、创建派生数组、应用函数、链式调用、异步数据流处理、复杂API请求梳理、提供DOM操作、用来搜索和过滤等,比for好用太多了,主要是写法简单,并且非常直观,并且能提升代码的可读性,也就提升了Long Term代码的可维护性。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
6月前
|
移动开发 运维 供应链
通过array.some()实现权限检查、表单验证、库存管理、内容审查和数据处理;js数组元素检查的方法,some()的使用详解,array.some与array.every的区别(附实际应用代码)
array.some()可以用来权限检查、表单验证、库存管理、内容审查和数据处理等数据校验工作,核心在于利用其短路机制,速度更快,节约性能。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
6月前
|
供应链 JavaScript 前端开发
通过array.every()实现数据验证、权限检查和一致性检查;js数组元素检查的方法,every()的使用详解,array.some与array.every的区别(附实际应用代码)
array.every()可以用来数据验证、权限检查、一致性检查等数据校验工作,核心在于利用其短路机制,速度更快,节约性能。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~