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

dashang.jpg

评论

14条评论
  1. Gravatar 头像

    365bet官网 回复

    写得很是独到,把外围的思惟都表白了进去。

  2. Gravatar 头像

    365bet体育在线官网 回复

    你好,请问小编可以让我转载这篇文章内容吗?我会备注原文出处链接的以及作者

  3. Gravatar 头像

    腾博会 回复

    很久没来看博主的文章了,说的很有道理,支持一下!

  4. Gravatar 头像

    腾博会 回复

    站长写得真是非常好,我要让我的朋友也看一下这篇风趣|有趣的文章

  5. Gravatar 头像

    ajex 回复

    可以

  6. Gravatar 头像

    m88明升 回复

    请问站长微信编辑页面是怎么做出来的?

  7. Gravatar 头像

    明升m88.com 回复

    便是这个留言板 能够设置成 显示最新的顺序

  8. Gravatar 头像

    彭江 回复

    非常喜欢你的文章,非常。。。好!

发表评论

电子邮件地址不会被公开。