JavaScript自定义“类”库

JavaScript 是基于原型的语言,在es6 之前并没有包含内置类的实现。但是这并不意味着类在JavaScript中毫无必要 。实际上类是一种很有用的工具,像其他编程语言中一样,类在JavaScript中同样可以起到重要的作用 。

下面我们手动封装一个类库,实现一个简单的类的创建。

预期实现的功能:

1.   可以对新创建出来的类进行初始化

2.   可以扩展类的静态属性与方法

3.   可以扩展类的实例的属性与方法

4.   在创建类时可以继承其他类的属性与方法。

代码实现:

varClass=function (parent) {

    // 初始化类库

    var _class =function () {

        this.init.apply(this,arguments); //将原型init方法上的属性同步到当前类

    }

    _class.prototype.init=function () { }

    // 动态扩展

    // 定义别名

    _class.fn=_class.prototype;

    _class.fn.parent=_class;

    // 给类添加属性和方法

    _class.extend=function (obj) {

        var extended = obj.extended;

        for(var i in obj)

        {

            _class[i] = obj[i]

        }

        if(extended) extended(_class); //回调,用于类自身扩展成功后的提示

    }

    // 给类的实例添加属性和方法

    _class.include=function (obj) {

         var included = obj.included;

         for(var i in obj)

         {

             _class.fn[i]=obj[i];

         }

         if(included) included(_class);// 回调,用于类实例扩展后的提示

    }

        // 给类添加继承

          if(parent)

          {

              var subclass=function () { };

              subclass.prototype =parent.prototype;

              _class.prototype = new subclass;

          }

      return _class;

}

// 使用“类”库

        var Cat = new Class();

        Cat.prototype.init=function(name,color) { // 对类进行初始化,修改为带有参数的类

            this.name = name;

            this.color = color;

            this.like = function () {

                return "fish";

            }

        }

        var cat = new Cat("mini","yellow");

        console.log( cat.name + " is"+ cat.color + " it like "+ cat.like());

           var Animal = new Class();

           Animal.prototype.init=function () {

                this.feed = "nurse";// 动物的喂养方式是哺乳

           }

           Animal.extend({  // 扩展类的静态属性和方法

                extended:function (_class){  //设置回调函数,用于扩展成功后的显示

                    console.log(_class+"is extended");

                },

                ClassName:"Animal"

           })

            Animal.include({ // 扩展类实例的属性和方法

               walk:"crawl",

               birth:function () {

               console.log("胎生哺乳");

            }})

           console.log(Animal.ClassName);

           var Dog = new Class(Animal);

           var dog = new Dog();

           console.log(dog.feed);

           console.log(dog.walk);

在开始分析上边的代码之前先和大家讨论一下原型的概念,关于原型有几个重要的点是我们需要了解的:

1.   我们将原型也称为“模板对象”,它上边的属性用来初始化一个新对象 。

2.   任何对象都可以作为另一个对象的原型对象,以此来实现属性共享 。

3.   我们也可以将原型理解为某种形式的继承。

代码详解:

首先因为我们的最终目的是想通过 Class函数 ,返回给我们一个构造函数 用于表示我们新创建的类 。所以只需要在Class 函数定义另一个构造函数(_class ),最终将其返回出来就好了。

在函数_class 的原型上定义一个init方法,并运用apply方法使_class继承自身prototype.init 方法。这样,当我们在新类的prototype.init 方法上进行初始化设置时,就会将内容同步到当前的类中。

关于属性和方法的扩展 。当我们要扩展的是类的静态属性和方法,只需要将传入的对象上的属性都复制到当前对象就可以了 。而如果我们需要对当前类的实例也进行属性和方法的扩展,就需要将传入的对象上的属性都复制到当前类的原型上 。 当然在这里我们加了一个回调函数的功能,用于扩展成功后的显示 (实际上如果你不能很好地理解,去除这一部分同样是可以的)。

给“类”库添加继承,我们传入的参数是一个可选的父类。注意如果将parent直接传入Class构造函数则所有子类都必然共享一个原型,这不是我们想要的结果。当然也不可以直接将parent的prototype与_class的prototype进行绑定,因为一旦这样做了,任何一方发生改变,另一个也将随之发生改变,这同样不是我们想要的结果。这里还有非常重要的一点需要我们记住:只有实例的属性才会被继承 。在这里我们通过创建匿名函数的小技巧,避免了在继承parent类的时候创建parent类的实例 。

猜你喜欢

转载自blog.csdn.net/tuohai_/article/details/72870521
今日推荐