为了账号安全,请及时绑定邮箱和手机立即绑定

JS学习:js面向对象编程(es6和jsface库技术选型)

面向对象的三大特性: 继承 封装 多态

1. 子类override基类同名方法时出现问题

原本要继续写渲染器方面的东西,但是在过程中遇到一个问题:根据JS学习:nodejs中的类定义和继承的套路的套路,发现一个致命的问题,无法对子类进行override,具体代码如下:

父类的render方法,绘制背景

BLFBaseSprite.prototype.render = function(render) {
    render.drawGrid('black', 'white', 10, 10);
}

子类override父类render方法,增加绘制文字

BLFBaseSprite.prototype.render = function(render) {
    render.drawGrid('black', 'white', 10, 10);
    render.drawText(10, 10, 'blue', "随风而行之青衫磊落险峰行测试RenderSurface");
}

测试代码:(创建的是BLFBaseSprite,原本是没有文字的,但是实际却显示了文字)

 var canvas = document.getElementById("myCanvas");
 var context = canvas.getContext('2d');
 var render = new BLFRender(context);
 var base= BLFBaseSprite();
 base.render(render);

出问题啦!!!

图片描述

原因: 是因为inherits函数中子类和父类的prototype指向的对象是同一个,共享了同一个prototype

也不想多花时间在这方面,于是决定选择是使用es6还是jsface库来进行js面向对象方式的编程。至于说typescript,是我非常喜欢的一门语言,但是客户端编程,就不选他了。

2. 测试es6和jsface面向对象编程的能力(继承 封装 多态)。

继承(包含子类覆写父类方法[override],以及子类调用父类方法)
jsface版本:

<script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://cdn.jsdelivr.net/jsface/2.4.9/jsface.min.js"></script>
<script>
        //Class方法1
        var Base = Class({
            constructor: function(name) {
                this.name = name;
            },

            toString: function() {
                return this.name;
            }
        });

        //Class重载方法进行继承
        var Child = Class(Base, {
            //构造函数增加一个id参数
            constructor: function(id, name) {
                this.id = id;
                //同时要调用基类的构造函数用于初始化name属性
                Child.$super.call(this, name);
            },

            //override 基类方法
            toString: function() {
                return this.name + '-' + this.id;
            }
        });

        var base = new Base("base");
        var child = new Child(1234, "child");
        alert(base.toString());
        alert(child.toString());
  </script>

上述代码可以在imooc中点击运行

es6版本:

<script>
       class ESBase {
            constructor(name) {
                this.name = name;
            }

            toString() {
                return this.name;
            }
        }

        class ESChild extends ESBase {
            constructor(id, name) {
                super(name); //调用基类方法
                this.id = id;
            }

            //override基类方法
            toString() {
                return this.name + '_' + this.id;
            }
        }

        var esBase = new ESBase("esBase");
        var esChild = new ESChild(4321, "esChild");
        alert(esBase.toString());
        alert(esChild.toString());
</script>

上述代码可以在imooc中点击运行

通过使用es6和jsface,完美解决今天碰到的问题。其威力来源与子类覆写父类方法[override],以及子类调用父类方法这两个关键功能。


封装(数据隐藏)
封装最简单的解释就是java c# c++等面向对象语言中的public/protected/private这些关键词起的作用:

  • public: 表明该数据成员、成员函数是对所有用户开放的,所有用户都可以直接进行调用
  • private:表示私有,私有的意思就是除了class自己之外,任何人都不可以直接使用,私有财产神圣不可侵犯嘛,即便是子女,朋友,都不可以使用。
  • protected:protected对于子女、朋友来说,就是public的,可以自由使用,没有任何限制,而对于其他的外部class,protected就变成private。

数据隐藏功能要在js中完美实现,难度非常大。并且感觉也没必要。数据隐藏最大的功能是隐藏实现细节,提供公开接口给第三方(面向接口编程)。js本身都是源码随意可见,因此封装数据隐藏也就不用考虑了。
为了使用代码更加清晰,可以自行设计相关规则,例如:

  • 使用_开头表示protected方法或属性
  • 使用__开头表示私有方法或属性

多态(函数地址运行时动态绑定)
其实多态是建立在继承和封装的基础上。强类型语言需要多态机制。js这种弱类型语言,天生就是运行时动态绑定函数地址的,因此天生支持。也不用多讲了。

反正一句话,js中只要解决继承(以及子类覆写父类方法[override],以及子类调用父类方法),我们就可以使用面向对象方式编程。也就解决了今天的一个关键问题。

3. 技术选型

测试结果(我电脑上最新版的浏览器):

浏览器 es6 jsface
chrome yes yes
firefox yes yes
opera yes yes
ms edge yes yes
ms ie11 no yes

目前ie11还不支持es6,其他浏览器都完美支持。

从语法简明,静态函数支持,箭头函数,let/const声明等等等等角度来说,我决定选择es6了
jsface兼容性的确非常不错,但是毕竟我们是使用canvas2d webgl为主,所以还是用es6吧

我们换吧!
换es6吧!

点击查看更多内容
2人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消