zoukankan      html  css  js  c++  java
  • javascript中最好用的extend继承方法

    从来没有正经写个文,今天开始要改改了。。

    javascript中的继承无非是new 一个函数,称为构造函数,叫什么无所谓,都是函数function,

    然后给这个方法的prototype添加一些方法,这些方法我们就说是继承过来的。

    javascript中有个概念叫做:“一切皆对象”,就是javascript存在都是对象,

    一个对象有2种属性,一种是继承过来的,一种是自己的,

    就像大自然的动物一样,从最基础的草履虫到现在的人类,都是一代代的继承扩展,实现丰富多样的世界,javascript的世界也模拟大自然的世界,包括其他语言也类似,软件的世界就是在模拟学习大自然规律。

    回到正题,javascript本身语言中没有实现标准的继承方法,

    那什么是标准的继承方法呢,就是一个语言中专门用来继承的。

    像php中有:

    Ancestor{
    
      //这里面写一大堆方法和属性,私有、共有的等等
       function __construct($options){
              $this->options= $options;
       }
       
      function run(){
            return 1;
      }
    
    };

    关于上面的语法,不懂的php的可以不用理会了,把上面代码写好之后就可以new 一下Class ,返回了一个对象了,上面的方法和属性可以在对象$obj使用了

    $obj = new Ancestor(1);

    然后继承呢,就是下面这么写

    Child extend Ancestor{ 
    //里面写一大堆方法属性,可以私有,可以公用等
    function __construct($options,$name){
      //执行一下父类的__construct方法
      parent::__construct();
       $this->name= $name;
    }
       function run(){
             $num =  parent::__construct();
          return $num +1;
    
      }
    
    }
    
    $childObj= new Child(1,'一只柯楠');

    上面的代码就是Child继承Ancestor的方法和属性了。。实例化也是new一下

    我们可以注意到当Child和Ancestor的方法重复时,我们可以使用parent::方法名来执行父类的方法,这样既可以不覆盖父类的方法,又可以自己扩展一些方法了,很方便。。。

    关键到了,

    javascript中是这样实现的

    var Ancestor= function(options){
                this.options= options;
    
                this.run=function(){
                         return 1;
               }
    }    
    //实例化Class
    var obj= new Ancestor;
    
    //写一个构造方法child
    var Child= function(){
          this.run= function(){
              return 2;
         }
    }
    //让child继承Ancestor
     Child.prototype= new Ancestor; 
    var  childObj= new Child(1,'一只柯楠');
    //然后给child这里继承之后,Child的run方法肯定会覆盖prototype里面的run方法。

    问题来了

    1、我们这里没有一个标准方法,先调用父类的重名的方法

    2、这样写Child.prototype= new Ancestor;很麻烦,很不规范,对于大项目来说很不统一可能有些人是这样child.prototype.run= function(){}等。。

    第一个问题的他解决办法也是有的,不错我个人认为比较搓,即是obj.run.apply(this,arguments);

    var Ancestor= function(options){
                this.options= options;
    
                this.run=function(){
                         return 1;
               }
    }    
    //实例化Class
    var obj= new Ancestor;
    
    //写一个构造方法child
    var Child= function(){
          this.run= function(){
              //这里就是先调用父类的run方法,不过你得直接写obj很不友好
              var num = obj.run.apply(this,arguments);
              return num+1;
         }
    }
    //让child继承Classh
    Child.prototype= obj;
    
    var  childObj= new Child(1,'一只柯楠');
    //然后给child这里继承之后,Child的run方法肯定会覆盖prototype里面的run方法。

    我们需要一个统一的继承方法解决上面的问题,我已经给大家写了详细的注释,

    好吧,

    其实写了上面那么多就是为了引出它存在的意义:

    (function(win,undefined){
        var initializing = false,
            superTest = /vnice/.test(function () {vnice;}) ? /\b_super\b/ : /.*/;
        this.Class = function () {};
    
        Class.extend = function (prop) {
            //_super和prototype:new建立一个新的对象,作为新类的prototype,不能直接在上面添加方法,会影响其他使用extend方法返回的类
            var _super = this.prototype;
            //设为true就不再执行init方法
            initializing = true;
            var prototype = new this();
            initializing = false;
            //将传进来的prop对象里的方法拷贝到prototype上面去
            for (var name in prop) {
                prototype[name] = (typeof prop[name] === 'function' && typeof _super[name] === 'function' && superTest.test(prop[name])) ? (function (name, fn) {
                //这一步为了实现,prop里面的某个方法(如prop.init)和原型prototype方法中的方法冲突时,可以在方法中调用【this._super()】,这里将this._super方法替换成原型中的这个方法(prototype.init).
                        return function () {
                            var temp = this._super;    
                            this._super = _super[name];
                            var ret = fn.apply(this, arguments);
                            this._super = temp;
                            return ret;
                        }
                    })(name, prop[name]) : prop[name];
            }
            
            function Class () {
                //构造函数中默认调用this.init方法
                if (!initializing && this.init) {
                    this.init.apply(this, arguments);
                }
            }
            //让将要返回的类继承prototype
            Class.prototype = prototype;
            //将类的构造函数设为Class
            Class.constructor = Class;
            //将类添加extend方法,方便继续继承
            Class.extend = arguments.callee;
            //返回构造函数
            return Class;
        };
    })(window,undefined)    

    上面的方法怎么使用呢???

    (function(){
    //class类的实现
    var Ancestor= Class.extend({
          init: function(options){
                 this.options= options;
         },
         run: function(){
                return 1;
        }
    });
    //实例化Class类
    var obj= new Ancestor();
    
    var Child= Ancestor.extend({
          init: function(options,name){
             //执行父类的init方法,类似PHP中的parent::init();
              this._super();
              this.name= name
         },
    
         run: function(){
              var num= this._super();
              return num+1;
         }
    });
    var  childObj= new Child(1,'一只柯楠');
    })()

    这样就可以生生不息,的继承扩展了。。说的不对的地方欢迎大牛指正。。。

     

     

  • 相关阅读:
    记录下python学习中,容易弄混和实用的知识点
    操作系统简史
    计算机结构
    计算机结构
    电脑简史
    电脑简史
    为什么学Python
    为什么学Python
    树莓派更换更新国内源
    树莓派更换更新国内源
  • 原文地址:https://www.cnblogs.com/webzhangnan/p/2910006.html
Copyright © 2011-2022 走看看