JavaScript ES6新的类继承特性学习笔记

Javascript新标准ES6正式出来都一年多了,最近才有时间愿意集中精力研究下,发现有些新特性确实亮瞎了我的双眼,比如,最新的“类-实例”的支持,再比如模仿Python引入gennerator等等。下面和大家分享下我ES6类继承的学习笔记吧。

JavaScript的标准——ECMAScript在不断发展,最新版ECMAScript 2015标准(简称ES6)已经在2015年6月正式发布了。新版本的ES有很多亮点,其中一个亮点就是正式引入了class关键字,开始正式支持面向对象的“类-实例”方式了。

0x01 比较

以前JavaScript的对象模型是基于原型实现的,特点是简单,缺点是理解起来比传统的“类-实例”模型要困难,最大的缺点是继承的实现需要编写大量代码,并且需要正确实现原型链。
下面是利用原型实现类继承的一种方式:

    'use strict';
        //动物原型
         function Animal(props){
             this.name=props.name||"未知";
         }
        Animal.prototype.eat=function(){
            alert(this.name+"在吃东西...");
        }

        //继承动物的鸟
        function Bird(props){
            Animal.call(this,props);
                this.type=props.type||”未知”;
        }
        function F(){}
        F.prototype=Animal.prototype;
        Bird.prototype=new F();
        Bird.prototype.constructor=Bird;
        Bird.prototype.fly=function(){
            alert(this.name+"在飞...");
        }

效果如下:

可见,为了实现类的继承,使用了中间量等大量辅助代码,废了多大功夫,不熟悉的人还不大理解。庆幸的是在ES6中,终于有了类似C++/PHP等语言那种真正意义上的“类-实例”模型了:

    'use strict';
        class Animal{
            //构造函数
            constructor(props){
                this.name=props.name||'未知';
            }

            eat(){
                alert(this.name+"在吃东西...");
            }
        }

        //class继承
        class Bird extends Animal{
            //构造函数
            constructor(props){
               //调用实现父类的构造函数
                super(props);
                this.type=props.type||"未知";
            }

            fly(){
                alert(this.name+"在飞...");
            }
        }

效果如下:

效果一样,但是是不是瞬间有种回到PHP代码的赶脚??看起来还是那么熟悉的姿势。嘿嘿。。。

0x02 转换

ES6中的class用起来是蛮爽的,但是,由于出来的比较晚了,不是所有的主流浏览器都支持ES6滴,况且不少童鞋还在用IE6呢,那么岂不是咱写代码时不敢用啦?幸运的是有个Babel的工具,可以实现自动从ES6转换为ES5。具体安装和使用有篇博客写的不错,可以参考下:Babel安装
,其实还可以直接用在线方式实现代码的装换(Babel在线转换):

上面ES6代码转换的结果如下:

'use strict';

        var _createClass = function () {
            function defineProperties(target, props) {
                for (var i = 0; i < props.length; i++) {
                    var descriptor = props[i];
                    descriptor.enumerable = descriptor.enumerable || false;
                    descriptor.configurable = true;
                    if ("value" in descriptor) descriptor.writable = true;
                    Object.defineProperty(target, descriptor.key, descriptor);
                }
            }

            return function (Constructor, protoProps, staticProps) {
                if (protoProps) defineProperties(Constructor.prototype, protoProps);
                if (staticProps) defineProperties(Constructor, staticProps);
                return Constructor;
            };
        }();

        function _possibleConstructorReturn(self, call) {
            if (!self) {
                throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
            }
            return call && (typeof call === "object" || typeof call === "function") ? call : self;
        }

        function _inherits(subClass, superClass) {
            if (typeof superClass !== "function" && superClass !== null) {
                throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
            }
            subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });
            if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
        }

        function _classCallCheck(instance, Constructor) {
            if (!(instance instanceof Constructor)) {
                throw new TypeError("Cannot call a class as a function");
            }
        }

        var Animal = function () {
            //构造函数

            function Animal(props) {
                _classCallCheck(this, Animal);

                this.name = props.name || '未知';
            }

            _createClass(Animal, [
                {
                    key: 'eat',
                    value: function eat() {
                        alert(this.name + "在吃东西...");
                    }
                }
            ]);

            return Animal;
        }();

        //class继承


        var Bird = function (_Animal) {
            _inherits(Bird, _Animal);

            //构造函数

            function Bird(props) {
                _classCallCheck(this, Bird);

                var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(Bird).call(this, props));

                _this.type = props.type || "未知";
                return _this;
            }

            _createClass(Bird, [
                {
                    key: 'fly',
                    value: function fly() {
                        alert(this.name + "在飞...");
                    }
                }
            ]);

            return Bird;
        }(Animal);

是不是又回到了基于原型实现的时代?这段代码就可以被一些老的浏览器支持了。

0x03 小结

现在,我们写javascript代码的时候,可以用一些ES6的新特性,比如class类继承等,然后再转换为ES5的标准,保证对一些老浏览器的兼容性。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值