从来没有正经写个文,今天开始要改改了。。
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,'一只柯楠'); })()
这样就可以生生不息,的继承扩展了。。说的不对的地方欢迎大牛指正。。。