类的使用和面向对象

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

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

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

我们来看一下这段代码:

var baselayer = cc.Layer.extend({
ctor:function(){
this._super();
cc.log("baselayer ctor read");
}, init:function(){
this._super();
cc.log("baselayer init read");
}
});

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

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

ClassManager.compileSuper.ClassManager = ClassManager;

/* Managed JavaScript Inheritance
* Based on John Resig's Simple JavaScript Inheritance http://ejohn.org/blog/simple-javascript-inheritance/
* MIT Licensed.
* 在这里申明了,实现JS继承的方式 是参考了 John Resig's 的一个例子来实现的;并且有原文地址,有兴趣的同学可以去看看原版实现方式
*/
(function () {
var fnTest = /\b_super\b/;
var config = cc.game.config;
var releaseMode = config[cc.game.CONFIG_KEY.classReleaseMode];
if(releaseMode) {
console.log("release Mode");
} /**
* The base Class implementation (does nothing)
* @class
*/
cc.Class = function () {
}; /**
* Create a new Class that inherits from this Class
* @static
* @param {object} props
* @return {function}
*/
cc.Class.extend = function (props) {
//声明_super对象,并赋值为原型
var _super = this.prototype; // Instantiate a base Class (but only create the instance,
// don't run the init constructor) //实例化创建prototype这个基类,只是创建实例,并没有跑init构造函数
var prototype = Object.create(_super); //给这个class复制ID标识,并且将_super对象添加到ClassManager类管理器中
var classId = ClassManager.getNewID();
ClassManager[classId] = _super;
// Copy the properties over onto the new prototype. We make function
// properties non-eumerable as this makes typeof === 'function' check
// unneccessary in the for...in loop used 1) for generating Class()
// 2) for cc.clone and perhaps more. It is also required to make
// these function properties cacheable in Carakan.
//进行函数的验证检测,以及设置他使用基本设置
var desc = { writable: true, enumerable: false, configurable: true }; //单例模式的基础申明
prototype.__instanceId = null; // The dummy Class constructor
//创建Class这个类
function Class() {
this.__instanceId = ClassManager.getNewInstanceId();
// All construction is actually done in the init method
//如果这个类他存在.ctor方法,那么就默认的使用执行这个方法
//ctor在JS中就相当于构造函数
if (this.ctor)
this.ctor.apply(this, arguments);
} //给ID复制
Class.id = classId;
// desc = { writable: true, enumerable: false, configurable: true,
// value: XXX }; Again, we make this non-enumerable.
desc.value = classId;
Object.defineProperty(prototype, '__pid', desc); // Populate our constructed prototype object
//把我们原型对象赋值
Class.prototype = prototype; // Enforce the constructor to be what we expect
//将整个类赋值给desc.value
desc.value = Class;
//并且将类里构造的对象赋值
Object.defineProperty(Class.prototype, 'constructor', desc); // Copy getter/setter
//模拟get/set的方式,使用cc.clone函数来拷贝
this.__getters__ && (Class.__getters__ = cc.clone(this.__getters__));
this.__setters__ && (Class.__setters__ = cc.clone(this.__setters__)); for(var idx = 0, li = arguments.length; idx < li; ++idx) {
var prop = arguments[idx];
for (var name in prop) {
var isFunc = (typeof prop[name] === "function");
var override = (typeof _super[name] === "function");
var hasSuperCall = fnTest.test(prop[name]); if (releaseMode && isFunc && override && hasSuperCall) {
desc.value = ClassManager.compileSuper(prop[name], name, classId);
Object.defineProperty(prototype, name, desc);
} else if (isFunc && override && hasSuperCall) {
desc.value = (function (name, fn) {
return function () {
var tmp = this._super; // Add a new ._super() method that is the same method
// but on the super-Class
//如果在新的对象方法里面添加._super(),他会继承父类的_super方法
//并且实现方法里面的所有对象及方法的赋值
this._super = _super[name]; // The method only need to be bound temporarily, so we
// remove it when we're done executing
var ret = fn.apply(this, arguments);
this._super = tmp; return ret;
};
})(name, prop[name]);
Object.defineProperty(prototype, name, desc);
} else if (isFunc) {
desc.value = prop[name];
Object.defineProperty(prototype, name, desc);
} else {
prototype[name] = prop[name];
} if (isFunc) {
// Override registered getter/setter
//如果是方法,那么重载里面的属性,并且实现get,set方法可以直接使用
var getter, setter, propertyName;
if (this.__getters__ && this.__getters__[name]) {
propertyName = this.__getters__[name];
for (var i in this.__setters__) {
if (this.__setters__[i] === propertyName) {
setter = i;
break;
}
}
cc.defineGetterSetter(prototype, propertyName, prop[name], prop[setter] ? prop[setter] : prototype[setter], name, setter);
}
if (this.__setters__ && this.__setters__[name]) {
propertyName = this.__setters__[name];
for (var i in this.__getters__) {
if (this.__getters__[i] === propertyName) {
getter = i;
break;
}
}
cc.defineGetterSetter(prototype, propertyName, prop[getter] ? prop[getter] : prototype[getter], prop[name], getter, name);
}
}
}
} // And make this Class extendable
// 可以使用Class.extend来实现类的继承
Class.extend = cc.Class.extend; //add implementation method
//添加要实现的方法
Class.implement = function (prop) {
for (var name in prop) {
prototype[name] = prop[name];
}
};
return Class;
};
})();

重点看3个点:

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

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

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

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

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

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

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

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

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

var myLayer = baselayer.extend({
ctor:function(){
this._super();
cc.log("myLayer ctor read");
}, init:function(){
this._super();
cc.log("myLayer init read");
}
});

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

var myLayer = baselayer.extend({});

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

并且日志输出一下;

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

如下:

var MainScene = cc.Scene.extend({
onEnter:function(){
this._super();
var layer = new myLayer();
this.addChild(layer);
}
});

我们首先只调用

var layer = new myLayer();

看看最终输出是什么?

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

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

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

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

 layer.init();

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

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

init 函数后执行;

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

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

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

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

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

var myLayer = baselayer.extend({
ctor:function(){
this._super();
cc.log("myLayer ctor read");
}, init:function(){
cc.log("myLayer init read");
}
});

看看输出:

 从输出看出,并没有执行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. Semantic-UI和其他几个前端框架

    本来是想介绍Semantic-UI的,但如果只介绍这个框架,没什么内容,框架相关feature站点上有不需要说,所以干脆列出自己常用的几个前端框架,算是做个阶段性总结. 本文的核心是侧重于HTML/C ...

  2. php redis 代码实例

    <?phpheader("Content-type:text/html;charset=utf8");$redis = new redis();$redis ->con ...

  3. 后台向前台输出 换行“\n”

    MVC 中后台向前台输出 "\n"总是报错 因为后台向前台输出 "\n" 后,前台出现换行  eg: "这里是\n换行" var str=& ...

  4. 在Visio2010中修改默认字体的大小

    由于我常需要在Visio2010中画流程图和UML图,但是Visio2010中的字体默认8px,这对眼睛是个挑战.摸索了好久终于找到在visio2010中修改字体大小的方式. 1.点一下红色箭头所指的 ...

  5. Spring依赖注入(IOC)那些事

    小菜使用Spring有几个月了,但是对于它的内部原理,却是一头雾水,这次借着工作中遇到的一个小问题,来总结一下Spring. Spring依赖注入的思想,就是把对象交由Spring容器管理,使用者只需 ...

  6. Backbone Collection——数据模型集合

    如果将一个Model对象比喻成数据库中的一条记录,那么Collection就是一张数据表.它表示为一个模型集合类,用于存储和管理一系列相同类型的模型对象. 1.创建集合集合用于组织和管理多个模型,但它 ...

  7. struts2学习笔记之一:基本简介

    Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个Servlet,在MVC设计模式中,Struts2作为控制器来建立模型与视图的数据交互(所有的访问都会被控制器操作控制)   ...

  8. paip.提升效率---提升绑定层次--form绑定取代field绑定

    paip.提升效率---提升绑定层次--form绑定取代field绑定 =================== 编辑form中,常常需要,绑定一个对象到个form..   传统上要绑定field开始. ...

  9. 通过swap代码分析C语言指针在汇编级别的实现

    我们先用C语言写一个交换两个数的代码: void swap(int *a, int *b){ int temp = *a; *a = *b; *b = temp; } int main(void) { ...

  10. Leetcode 198 House Robber 动态规划

    题意是强盗能隔个马抢马,看如何获得的价值最高 动态规划题需要考虑状态,阶段,还有状态转移,这个可以参考<动态规划经典教程>,网上有的下的,里面有大量的经典题目讲解 dp[i]表示到第i匹马 ...