createjs进阶—createjs的OOP
OOP大家都知道就是面向对象编程,对于程序构建,特别是大项目,可以说是必不可少的。可以用它来降低开发难度,提高代码的重用率等等。在createjs里可以用它特有的写法和api来实现OOP。无论你是从as转到js,还是本来就是写js的,学会在createjs里使用OOP编程都是很重要的,废话不多说,我直接讲下怎么在createjs里使用OOP。
(不懂OOP的请先了解OOP后再看本教程)
1.类一般语言(我先拿as作为例子),生成一个类一般是
public class MainView 然后调用的是 new MainView()这样子,在js里没有类这个概念,但是我们可以模仿,写一个差不多的。
我们先写出类:
function Map(){ this.name = "中国" } var map = new Map(); console.log(map.name)
可以看到我们就输出了地图,这里的Map相当于构造函数
2.闭包
(function() { function Map(){ this.name = "地图" } var map = new Map(); }()); console.log(map);
大家上面还看到了一个(function() {}());这个格式的语法吧,这个东西干嘛用的呢,做过前端的童鞋肯定知道,它叫闭包。简单的来说吧,就是防止变量之间污染,js与类java语言不一样,类java语言比如as3,他在类里面var的变量只在类里面有用,但是js是都有用,这样的话项目一大变量之间就容易相互污染,而闭包可以很好的解决这问题,写as3转js的童鞋可以把它当做package包。这里的console因为在包外面,所以会报错。
3.继承
继承是非常重要的OOP方法,思考一下你做游戏的时候要new10个不同的角色,如果他们都间接继承与一个基础角色类,那么你要统一改他们的方法,只需要改一个方法,而不是改十个。
这回就要用到createjs的继承api了。
function Map(){ this.name = "地图" } var map = new Map(); var cls = {}; (function() { function ChinaMap(){ this.Map_constructor();//构造 } var p = createjs.extend(ChinaMap,Map);//继承 p.from = "中国"; p.changeFrom = function (data) { // p.from = data;//这样就会出错 输出2个美国 this.from = data; } cls.ChinaMap = createjs.promote(ChinaMap, "Map");//提升 }()); var map1 = new cls.ChinaMap(); var map2 = new cls.ChinaMap(); map1.changeFrom("美国"); console.log(map1.from,map2.from,map1.name,map2.name);
输出出来是 美国 中国 地图 地图。
ChinaMap继承了map的属性,所以map1和map2输出name,都能输出Map中的name。这里的createjs.extend相当于,OOP语言里的extend。而我定义的cls相当于是我保存类的一个地方。而这里的p就是继承后对象的原型链,在p中可以定义方法,定义属性,当然在构造中也可以定义方法和属性。
另外大家也看到了,类里面的方法是不能用原型链来调用方法和修改属性的,因为如果调用所有实例化这个类的对象都会被调用到,所有的属性也都会被修改。
注意:animteCC调出来的类,继承需要特殊的继承写法,文章结尾介绍。还有,平时写as的童鞋写显示类的时候通常会继承Sprite 而在createjs中可以选择继承Container,千万不要也继承Sprite flash as的sprite和createjs的sprite不是一种东西
4.提升
createjs.promote大家可能会觉得陌生,他是createjs特有的处理方法,也是非常聪明的做法,他的作用是“提升”,什么意思呢?其实就是让当前类可以调用其父类爷爷类祖宗类,也就是类名_方法名就可以调用了
function Map(){ this.name = "地图" } var map = new Map(); var cls = {}; (function() { function ChinaMap(){ this.Map_constructor(); this.city = "北京"; this.traceCity = function ()//构造中的方法不会被提升 { console.log(this.city,this.from); } } var p = createjs.extend(ChinaMap,Map); p.from = "中国"; p.traceFrom = function traceFrom() { console.log(this.from,this.city); } cls.ChinaMap = createjs.promote(ChinaMap, "Map"); }()); (function() { function HZMap(){ this.ChinaMap_constructor(); this.traceCity = function () { console.log(this.ChinaMap_city,this.ChinaMap_from); } } var p = createjs.extend(HZMap,cls.ChinaMap); p.traceFrom = function traceFrom()//这里就是重写了父类的方法 { console.log(this.ChinaMap_from,this.ChinaMap_city); } cls.HZMap= createjs.promote(HZMap, "ChinaMap"); }()); var hzMap = new cls.HZMap(); console.log(hzMap.ChinaMap_from);//undefined 只有方法会被提升 hzMap.ChinaMap_traceFrom();//中国 北京 //hzMap.ChinaMap_traceCity();//这里会出错 只有原型链中的方法会被提升 hzMap.traceFrom();//undefined undefined 只有方法会被提升 内部调用一样不行
在上面的代码中,大家可以看到,子类虽然重写了父类的方法,但是依然可以调用父类的方法,只需要父类_方法就可以了,当然,只有原型链中的方法,才会被提升。
很多人会忽视提升的作用,其实提升除了可以调用父类方法,还可以使继承来的属性“合法化”。
var cls = {}; function People(){ this.name = "李小龙" } //(function() { // function GodPeople(){ // this.__proto__.__proto__.constructor(); // } // var p = createjs.extend(GodPeople,People); // cls.GodPeople = GodPeople; //}()); //var people = new cls.GodPeople(); //console.log(people.name); //console.log(people.hasOwnProperty("name"))//这里输出的是false (function() { function GodPeople(){ this.People_constructor(); } var p = createjs.extend(GodPeople,People); cls.GodPeople= createjs.promote(GodPeople, "People"); }()); var people = new cls.GodPeople(); console.log(people.name); console.log(people.hasOwnProperty("name"))//这里输出的true
在上面代码中,如果使用上面注释中的代码,检查属性的时候属性就不属于该类本身,原因也很简单,因为这个属性是属于他父类的。(这个问题在很多js框架中都会被忽视,但是createjs却解决了这个问题,说明createjs的团队只是懒,能力还是很强的么^_^)
5.构造
构造简单的讲就是类的初始化方法,在js中constructor相当于构造函数,也就是经过上面的代码提升后,this.Map_construtor就是调用父类的构造函数,是写一个类必须的,相当于as3的this.super();
6.重写
重写的话,直接在构造或者原型链中重新定义属性或者方法就可以了,但是由于构造中的方法不会被提升,所以重写也尽量在原型链中重写。
7.公有私有 js没有 public private protected 等控制属性方法权限的语句,私有方法直接写在闭包内就可以了。
(function() { var _no;//私有属性 var _run;//私有方法 function HZMap(){ this.ChinaMap_constructor(); this.from = "中国"; this.city = "杭州"; _no = "123456" _run = function () { console.log("我是一张底图,但是我不会跑。") } } var p = createjs.extend(HZMap,cls.ChinaMap); p.traceFrom = function traceFrom() { //这里是类的内部,可以访问 console.log(this.from,this.city,_no); _run(); } cls.HZMap= createjs.promote(HZMap, "ChinaMap"); }()); var hzMap = new cls.HZMap(); hzMap.traceFrom(); console.log(hzMap._no,hzMap._run);//这里由于是类的外部,访问不到私有属性和方法
但是这和一般语言中的私有还是有区别的,一般语言中的私有,你虽然不能用,但是在查看表达式的时候还是看得到的。但是在这里的私有,你在外面是看不到的。所以从架构的角度讲,不要使用上面那种私有。直接在需要私有的属性或方法的命名上写个下划线“_”,程序员之间做个约束,看到带下划线的属性不要去改他就好了。
(并且你还要保证类只new一次,不然二次以上私有属性方法就会在各个new出来的对象中污染了,总之这种私有方法不推荐)
↑ 封装类必不可少的东西
另外还有一个问题,在没有createjs的环境下也能使用这些oop的api吗,答案是可以的,我还特意把相关代码提取了出来,只要把下面的代码放入项目中,不引入createjs,也能使用oop的api
this.oop = this.oop||{}; oop.extend = function(subclass, superclass) { function o() { this.constructor = subclass; } o.prototype = superclass.prototype; return (subclass.prototype = new o()); }; oop.promote = function(subclass, prefix) { var subP = subclass.prototype, supP = (Object.getPrototypeOf&&Object.getPrototypeOf(subP))||subP.__proto__; if (supP) { subP[(prefix+="_") + "constructor"] = supP.constructor; // constructor is not always innumerable for (var n in supP) { if (subP.hasOwnProperty(n) && (typeof supP[n] == "function")) { subP[prefix + n] = supP[n]; } } } return subclass; };
就这么简单的2个方法……
最后讲一下,animateCC生成的类怎么继承,直接上代码:
var cls = {}; cls.MyMc = function MyMc(){ this.__proto__ = new lib.mc(); } var mc = new cls.MyMc(); mc.stop(); stage.addChild(mc);
大家可以看到由于animateCC生成mc的方式不同,导致我们也只能用类似的方式来继承。
本篇文章对于不熟悉OOP的同学来说相当晦涩难懂,没关系,不懂的童鞋可以到官方讨论群咨询。群号:320648191。
匿名
其实可以直接引入外部的 js 文件,然后在外部的 js 里面写好复杂的函数,最后导出一个变量到window全局中,最后使用变量就好了,如果是熟悉 es6 的同学,直接使用 class 进行对象创建等操作都可以,AN 中的js好像还是es3,很难受
彭江
非常喜欢你的文章,非常。。。好!
明升m88.com
便是这个留言板 能够设置成 显示最新的顺序
明升m88.com
不错哦。。博客做的真棒啊。。
m88明升
请问站长微信编辑页面是怎么做出来的?
ajex
@m88明升 什么微信编辑页面
ajex
可以
伟德国际
过来看看本博客,博主记得回访哦
腾博会
站长写得真是非常好,我要让我的朋友也看一下这篇风趣|有趣的文章
腾博会
很久没来看博主的文章了,说的很有道理,支持一下!
伟德国际
赞一个 非常不错 很有个性
365bet体育在线官网
你好,请问小编可以让我转载这篇文章内容吗?我会备注原文出处链接的以及作者
ajex
@365bet体育在线官网 可以
伟德国际
也欢送博主到我的博客瞧一瞧!
365bet官网
写得很是独到,把外围的思惟都表白了进去。