类的使用和面向对象

大家都知道在cocos2d-x 底层是C++编写的,那么就有类的概念和继承机制。

但是在JS中,是没有类这个概念的,没有提供类,没有C++的类继承机制。

那么JS是通过什么方式实现简单的继承呢?JS是通过对象的原型实现继承。

我们来看一下这段代码:

  1. var baselayer = cc.Layer.extend({
  2. ctor:function(){
  3. this._super();
  4. cc.log("baselayer ctor read");
  5. },
  6.  
  7. init:function(){
  8. this._super();
  9. cc.log("baselayer init read");
  10. }
  11. });

我们申明了baseLayer对象 ,并且利用cc.Layer.extend,继承了CClayer。

那么问题来了?他究竟是怎么实现的呢?我们按住crtl跟进去看看cc.Layer.extend的实现;

  1. ClassManager.compileSuper.ClassManager = ClassManager;
  2.  
  3. /* Managed JavaScript Inheritance
  4. * Based on John Resig's Simple JavaScript Inheritance http://ejohn.org/blog/simple-javascript-inheritance/
  5. * MIT Licensed.
  6. * 在这里申明了,实现JS继承的方式 是参考了 John Resig's 的一个例子来实现的;并且有原文地址,有兴趣的同学可以去看看原版实现方式
  7. */
  8. (function () {
  9. var fnTest = /\b_super\b/;
  10. var config = cc.game.config;
  11. var releaseMode = config[cc.game.CONFIG_KEY.classReleaseMode];
  12. if(releaseMode) {
  13. console.log("release Mode");
  14. }
  15.  
  16. /**
  17. * The base Class implementation (does nothing)
  18. * @class
  19. */
  20. cc.Class = function () {
  21. };
  22.  
  23. /**
  24. * Create a new Class that inherits from this Class
  25. * @static
  26. * @param {object} props
  27. * @return {function}
  28. */
  29. cc.Class.extend = function (props) {
  30. //声明_super对象,并赋值为原型
  31. var _super = this.prototype;
  32.  
  33. // Instantiate a base Class (but only create the instance,
  34. // don't run the init constructor)
  35.  
  36. //实例化创建prototype这个基类,只是创建实例,并没有跑init构造函数
  37. var prototype = Object.create(_super);
  38.  
  39. //给这个class复制ID标识,并且将_super对象添加到ClassManager类管理器中
  40. var classId = ClassManager.getNewID();
  41. ClassManager[classId] = _super;
  42. // Copy the properties over onto the new prototype. We make function
  43. // properties non-eumerable as this makes typeof === 'function' check
  44. // unneccessary in the for...in loop used 1) for generating Class()
  45. // 2) for cc.clone and perhaps more. It is also required to make
  46. // these function properties cacheable in Carakan.
  47. //进行函数的验证检测,以及设置他使用基本设置
  48. var desc = { writable: true, enumerable: false, configurable: true };
  49.  
  50. //单例模式的基础申明
  51. prototype.__instanceId = null;
  52.  
  53. // The dummy Class constructor
  54. //创建Class这个类
  55. function Class() {
  56. this.__instanceId = ClassManager.getNewInstanceId();
  57. // All construction is actually done in the init method
  58. //如果这个类他存在.ctor方法,那么就默认的使用执行这个方法
  59. //ctor在JS中就相当于构造函数
  60. if (this.ctor)
  61. this.ctor.apply(this, arguments);
  62. }
  63.  
  64. //给ID复制
  65. Class.id = classId;
  66. // desc = { writable: true, enumerable: false, configurable: true,
  67. // value: XXX }; Again, we make this non-enumerable.
  68. desc.value = classId;
  69. Object.defineProperty(prototype, '__pid', desc);
  70.  
  71. // Populate our constructed prototype object
  72. //把我们原型对象赋值
  73. Class.prototype = prototype;
  74.  
  75. // Enforce the constructor to be what we expect
  76. //将整个类赋值给desc.value
  77. desc.value = Class;
  78. //并且将类里构造的对象赋值
  79. Object.defineProperty(Class.prototype, 'constructor', desc);
  80.  
  81. // Copy getter/setter
  82. //模拟get/set的方式,使用cc.clone函数来拷贝
  83. this.__getters__ && (Class.__getters__ = cc.clone(this.__getters__));
  84. this.__setters__ && (Class.__setters__ = cc.clone(this.__setters__));
  85.  
  86. for(var idx = 0, li = arguments.length; idx < li; ++idx) {
  87. var prop = arguments[idx];
  88. for (var name in prop) {
  89. var isFunc = (typeof prop[name] === "function");
  90. var override = (typeof _super[name] === "function");
  91. var hasSuperCall = fnTest.test(prop[name]);
  92.  
  93. if (releaseMode && isFunc && override && hasSuperCall) {
  94. desc.value = ClassManager.compileSuper(prop[name], name, classId);
  95. Object.defineProperty(prototype, name, desc);
  96. } else if (isFunc && override && hasSuperCall) {
  97. desc.value = (function (name, fn) {
  98. return function () {
  99. var tmp = this._super;
  100.  
  101. // Add a new ._super() method that is the same method
  102. // but on the super-Class
  103. //如果在新的对象方法里面添加._super(),他会继承父类的_super方法
  104. //并且实现方法里面的所有对象及方法的赋值
  105. this._super = _super[name];
  106.  
  107. // The method only need to be bound temporarily, so we
  108. // remove it when we're done executing
  109. var ret = fn.apply(this, arguments);
  110. this._super = tmp;
  111.  
  112. return ret;
  113. };
  114. })(name, prop[name]);
  115. Object.defineProperty(prototype, name, desc);
  116. } else if (isFunc) {
  117. desc.value = prop[name];
  118. Object.defineProperty(prototype, name, desc);
  119. } else {
  120. prototype[name] = prop[name];
  121. }
  122.  
  123. if (isFunc) {
  124. // Override registered getter/setter
  125. //如果是方法,那么重载里面的属性,并且实现get,set方法可以直接使用
  126. var getter, setter, propertyName;
  127. if (this.__getters__ && this.__getters__[name]) {
  128. propertyName = this.__getters__[name];
  129. for (var i in this.__setters__) {
  130. if (this.__setters__[i] === propertyName) {
  131. setter = i;
  132. break;
  133. }
  134. }
  135. cc.defineGetterSetter(prototype, propertyName, prop[name], prop[setter] ? prop[setter] : prototype[setter], name, setter);
  136. }
  137. if (this.__setters__ && this.__setters__[name]) {
  138. propertyName = this.__setters__[name];
  139. for (var i in this.__getters__) {
  140. if (this.__getters__[i] === propertyName) {
  141. getter = i;
  142. break;
  143. }
  144. }
  145. cc.defineGetterSetter(prototype, propertyName, prop[getter] ? prop[getter] : prototype[getter], prop[name], getter, name);
  146. }
  147. }
  148. }
  149. }
  150.  
  151. // And make this Class extendable
  152. // 可以使用Class.extend来实现类的继承
  153. Class.extend = cc.Class.extend;
  154.  
  155. //add implementation method
  156. //添加要实现的方法
  157. Class.implement = function (prop) {
  158. for (var name in prop) {
  159. prototype[name] = prop[name];
  160. }
  161. };
  162. return Class;
  163. };
  164. })();

重点看3个点:

  1. // The dummy Class constructor
  2. //创建Class这个类
  3. function Class() {
  4. this.__instanceId = ClassManager.getNewInstanceId();
  5. // All construction is actually done in the init method
  6. //如果这个类他存在.ctor方法,那么就默认的使用执行这个方法
  7. //ctor在JS中就相当于构造函数
  8. if (this.ctor)
  9. this.ctor.apply(this, arguments);
  10. }

第一,这个是在JS中的实现构造函数的方法,如果在自定义类中,存在有ctor:function()这个方法,那么他会

默认执行,默认成为构造函数;

  1. desc.value = (function (name, fn) {
  2. return function () {
  3. var tmp = this._super;
  4.  
  5. // Add a new ._super() method that is the same method
  6. // but on the super-Class
  7. //如果在新的对象方法里面添加._super(),他会继承父类的_super方法
  8. //并且实现方法里面的所有对象及方法的赋值
  9. this._super = _super[name];
  10.  
  11. // The method only need to be bound temporarily, so we
  12. // remove it when we're done executing
  13. var ret = fn.apply(this, arguments);
  14. this._super = tmp;
  15.  
  16. return ret;
  17. };
  18. })(name, prop[name]);

第二,desc.value在这个for循环中的赋值,实现了this._super()的原理,它会为派生类实完成对父类的实现;

通俗点来说,就是,如果我们想要继承并实现父类的方法,那么就需要在方法里面调用this._super()这个方法!

  1. // And make this Class extendable
  2. // 可以使用Class.extend来实现类的继承
  3. Class.extend = cc.Class.extend;

第三,讲cc.Class.extend赋值给Class.extend,就可以使用Class.extend来实现自定义类的继承;

OK,梳理完毕下面看看我们来学习一下怎么实现自定义类和自定义的继承:

  1. var myLayer = baselayer.extend({
  2. ctor:function(){
  3. this._super();
  4. cc.log("myLayer ctor read");
  5. },
  6.  
  7. init:function(){
  8. this._super();
  9. cc.log("myLayer init read");
  10. }
  11. });

这段代码中我从myLayer继承了父类baselayer,注意用法就是刚才我们Review底层代码时看到的

var myLayer = baselayer.extend({});

然后继续续实现ctor构造方法函数,和自定义方法函数init;

并且日志输出一下;

最终我们需要在MainScene中调用;

如下:

  1. var MainScene = cc.Scene.extend({
  2. onEnter:function(){
  3. this._super();
  4. var layer = new myLayer();
  5. this.addChild(layer);
  6. }
  7. });

我们首先只调用

var layer = new myLayer();

看看最终输出是什么?

从输出可以看出他先调用了baselayer,再调用了myLayer;

那么就可以理解为我们直接new myLayer() 会直接自动实现调用我们写的ctor构造函数方法;

而且是先调用父类,然后再调用我们的派生类自定义类;

他并没有主动调用init:function()这个方法,因为他是我们自定义的,所以需要我们手动去调用

  1. layer.init();

OK,我们加上手动调用后再来看一下输出是什么?

我们可以看到了前两行输出都是 ctor 先执行;

init 函数后执行;

而且调用也是 先执行baseLayer 我们的父类的init函数 再执行我们的自定义init方法!

现在就非常清晰了,我们的myLayer.init方法继承了baseLayer.init的属性方法;

而且实现的原理就是通过this._super()来实现的!

我们再修改一下代码来看看是不是这样,将myLayer类里面的init方法里面的this._super();这句话去掉!

看看我们的baseLayer.init方法会不会被调用

  1. var myLayer = baselayer.extend({
  2. ctor:function(){
  3. this._super();
  4. cc.log("myLayer ctor read");
  5. },
  6.  
  7. init:function(){
  8. cc.log("myLayer init read");
  9. }
  10. });

看看输出:

 从输出看出,并没有执行baseLayer 的init方法函数,那么也就验证了this._super();的作用;
this._super()调用实现了对父类的继承,包括父类相同名方法里面的参数的继承;
这段很精辟的代码就大概介绍了 在cocos2dx-Js中如何实现类,和类的继承的概念;
有了面向对象的编程概念后我们以后在cocos2dx-Js中,实现更复杂的逻辑实现和功能实现就变得非常容易了!
本教程结束;
 
本教程视地址频在:
想通过视频学习本教程的童鞋可以进入九秒课堂观看本章节视频;
 
 
 
 
 
 

【Cocos2d-Js基础教学(2)类的使用和面向对象】的更多相关文章

  1. js基础回顾-数据类型和typeof怎么用

    js的基本数据类型有六种,undefined.null.number.string.boolean.object. 未定义        空      数字        字符串    布尔     ...

  2. 前端工程师面试问题归纳(一、问答类html/css/js基础)

    一.参考资源 1.前端面试题及答案整理(一) 2.2017年前端面试题整理汇总100题 3.2018最新Web前端经典面试试题及答案 4.[javascript常见面试题]常见前端面试题及答案 5.W ...

  3. 【Cocos2d-Js基础教学 入门目录】

    本教程视地址频在: 九秒课堂 完全免费 从接触Cocos2dx-Js以来,它的绽放的绚丽让我无法不对它喜欢.我觉得Js在不断带给我们惊喜:在开发过程中,会大大提升我们对原型开发的利用率,使用Js语言做 ...

  4. js 基础

    js基础知识点总结 如何在一个网站或者一个页面,去书写你的js代码:1.js的分层(功能):jquery(tool) 组件(ui) 应用(app),mvc(backboneJs)2.js的规划():避 ...

  5. JS基础知识总结

      js基础知识点总结 如何在一个网站或者一个页面,去书写你的js代码:1.js的分层(功能):jquery(tool) 组件(ui) 应用(app),mvc(backboneJs)2.js的规划() ...

  6. js基础篇——call/apply、arguments、undefined/null

    a.call和apply方法详解 call方法: 语法:call([thisObj[,arg1[, arg2[,   [,.argN]]]]]) 定义:调用一个对象的一个方法,以另一个对象替换当前对象 ...

  7. js基础知识总结(2016.11.1)

    js基础知识点总结 如何在一个网站或者一个页面,去书写你的js代码:1.js的分层(功能):jquery(tool) 组件(ui) 应用(app),mvc(backboneJs)2.js的规划():避 ...

  8. JS表单验证类HTML代码实例

    以前用的比较多的一个JS表单验证类,对于个人来说已经够用了,有兴趣的可以在此基础上扩展成ajax版本.本表单验证类囊括了密码验证.英文4~10个 字符验证. 中文非空验证.大于10小于100的数字.浮 ...

  9. 【 js 基础 】Javascript “继承”

    是时候写一写 "继承"了,为什么加引号,因为当你阅读完这篇文章,你会知道,说是 继承 其实是不准确的. 一.类1.传统的面向类的语言中的类:类/继承 描述了一种代码的组织结构形式. ...

随机推荐

  1. 【Python自动化运维之路Day4】

    abs()  取绝对值all()  所有为真,则为真,否则为假any()  至少有一个为真,就为真,否则为假callable()   判断函数是否可以被调用,如果可以返回True,否则返回False ...

  2. json原理和jquey循环遍历获取所有页面元素

    1.json原理: javascript object notation (javascript 对象表示法) 是一种轻量级的数据交换语言,由javascript衍生而出,适用于.NET java c ...

  3. 一步一步搭建客服系统 (3) js 实现“截图粘贴”及“生成网页缩略图”

    最近在做一个客服系统的demo,在聊天过程中,我们经常要发一些图片,而且需要用其它工具截图后,直接在聊天窗口里粘贴,就可以发送:另外用户输入一个网址后,把这个网址先转到可以直接点击的link,并马上显 ...

  4. Dynamic CRM 2013学习笔记(四十六)简单审批流的实现

    前面介绍过自定义审批流: Dynamic CRM 2013学习笔记(十九)自定义审批流1 - 效果演示 Dynamic CRM 2013学习笔记(二十一)自定义审批流2 - 配置按钮 Dynamic ...

  5. 如何在Global.asax中判断是否是ajax请求

    今天在一个应用场景中需要在Global.asax中判断一个请求是否是ajax请求,而在ASP.NET MVC中已经提供了一个现成的扩展方法IsAjaxRequest: namespace System ...

  6. MSTest、NUnit、xUnit.net 属性和断言对照表

    MSTest.NUnit.xUnit.net 属性对照表 MSTest NUnit xUnit.net Comments [TestMethod] [Test] [Fact] Marks a test ...

  7. js继承精益求精之寄生式组合继承

    一.混合/组合继承的不足 上一篇JS继承终于混合继承,认真思考一下,发现其还是有不足之处的: 空间上的冗余:在使用原型链的方法继承父类的原型属性(Animal.prototype)的同时,也在子类的原 ...

  8. servlet web文件上传

    web文件上传也是一种POST方式,特别之处在于,需设置FORM的enctype属性为multipart/form-data. 并且需要使用文件域. servlet的代码比较关键是这几句: // 使用 ...

  9. Web调试工具——Fiddler介绍

    Fiddler 教程 Fiddler是最强大最好用的Web调试工具之一,它能记录所有客户端和服务器的http和https请求,允许你监视,设置断点,甚至修改输入输出数据. 使用Fiddler无论对开发 ...

  10. Django实现一个相片管理系统01

    有些日子没写笔记,O(∩_∩)O哈哈~实在是肚子没有墨水啦!今天不写数据结构啦!多怀念研究数据结构的日子啊! 可是呢!最近有个项目要搞图像管理方面的,具体内容就不说啦!我们今天来实现一个简单的相册管理 ...