ES里面没有真正的继承,但是能通过某些手段达到继承效果,从而让一个类拥有另外一个类的方法 类 =>构造函数
继承描述某语言环境---魔兽世界 哈!其实我没玩过 魔兽世界里面 有Humen类 Humen类里面有Gnome(侏儒) , gnome有方法say(我的名字)
有共有属性ggroup=gnome ,humen 有共有属性hgroup=humen , 有自己名字 hname 共有方法write();
总共共3种继承方式 一种类继承 一种是原型继承 还有一种组合继承 至于其他的继承方式,本质上没啥区别
function humen(name){ //人类类 this.name=name; this.write=function(){ console.log("write") } } humen.prototype.hgroup="humen"; new humen('张三'); //传统的是在gnome里面建立一个temp属性 指向humen构造函数,从而去用humen里面this指向ganme 然后去初始化gnome里面的属性和方法(略) /**下面是类继承 */ function gnome(name){ this.say=function(){ console.log(this.name); }; humen.call(this,name); } gnome.prototype.ggroup="gnome"; var gnome=new gnome("李四"); console.log(gnome.name); //"李四" console.log(gnome.hgroup);//"underfined" 由此可以得出这种继承方式只是借用call 或者apply 来改变this 借用构造函数初始化属性和方法 //无法继承原型上面的属性和方法 /*************************下面是原型继承 ***********************/ function gnome(name){ this.name=name; this.say=function(){ console.log(this.name); } } gnome.prototype.ggroup="gnome"; gnome.prototype=new humen(); // 这里把一些公共的参数传进去。。。 var gnome=new gnome("李四"); gnome.say();//李四 console.log(gnome.hgroup); //humen 由此得出这种继承方式能够继承原型链上面的属性和方法 但是个体的方法(this.name)需要重新写一遍 /*************************都用的不爽 前面2种一种不能继承原型 一种构造函数里面的属性需要重新定义 混合继承***********************/ function gnome(name){ this.say=function(){ //自己的方法 console.log(this.name); }; humen.call(this,name); } gnome.prototype=new humen(); //new humen里面name属性是undefined 被类继承的name覆盖 gnome.prototype.ggroup="gnome"; var gnome1=new gnome("李四"); gnome1.say();//李四 gnome.prototype.constructor=gnome; //由于用原型继承 构造函数方向指向humen console.log(gnome1.hgroup);//"humen" console.log(gnome1.ggroup); //"gnome"
总结:每使用new 关键字new一个对象都是在创建一个空对象,改变this指针指向空对象,然后初始化其中属性和方法,还有_proto_指向原型对象,所以对于一些公用的属性和方法定义在原型对象之中,避免浪费内存,私有的(与参数相关)则放在构造函数中。类继承和原型继承都有各自的弊端,组合继承则互补,实现完美继承,注意constructor的指向
另外附上某处偷来的,自己觉得比较好的js世界里面的原型链图: