js中六种继承方式

1、原型链继承

//     通过将自己的原型继承于另外一个构造函数创建出来的对象,将被继承的对象中的所有属性都存在于__proto__属性中.

//     缺点:

//         1)原型链继承多个实例的引用属性指向相同,改变一个会影响另一个实例的属性.

//                如果是引用类型的,继承的是地址,那么子原型中的引用地址和父对象中的引用地址相同

//         2)不能传递参数

//             因为是原型上继承所以不能传递参数

//         3)继承单一

           function Father(){

              this.FatherName = "father's 构造函数";

           }

           Father.prototype.age = 40;

           function Son(){

              this.SonNname = "Son's 构造函数";

           }

           //Son的原型继承Father创建出来的对象,相当于继承了Father的全部内容,同时全部都存在Son__proto__属性里

           Son.prototype = new Father();

           Son.prototype.getSubValue = false;

           Son.prototype.age1 = 20;

           var example =new Son();

           console.log(example.age);

 

2、借用构造函数继承

    使用call()和apply()将父类构造函数引入到子类函数,使用父类的构造函数来增强子类的实例,等同于复制父类的实例给子类

    这种方法就是通过call()apply(),完完全全复制了一份给子类,所以子类的任何操作都不会影响到父类

       缺点:

           只能继承父类的实例属性和方法,不能继承到原型中的内容

           无法实现构造函数的复用,每个子类都有父类实例函数的副本,影响性能,代码会臃肿

           function Father(name){

              this.name = name;

              this.colors = ["red"];

           }

           Father.prototype.sex = 1;

           function Son(name,age){

              Father.call(this,name);//利用call改变this的指向将this指向父类中的name,这样就把Father中方法给引入到子类中了

              this.age = age;

           }

           var obj = new Son("张三",25);

           obj.colors.push("write");   //引用类型的也不会改变父类中的内容

           console.log(obj.colors);// [red write]

           var obj2= new Son("jike",10);

           console.log(obj2.colors);//[red]

           console.log(obj2.sex);//undefined 无法继承到父类原型中的内容

3,组合继承

//  将原型链继承和构造函数继承这两种模式的有点组合在一起,通过调用父类构造,继承父类的属性并保留传参,然后通过将父类实例作为子类原型,实现函数复用.

           缺点:

               父类中的实例属性,方法即存在子类的实例中,也存在于子类的原型中,占内存

              同时也继承了以上的优点和缺点,

              对于引用类型的数据,子类实例对其操作会影响到父类中的

           优点:既可以继承到父类的原型中的方法,也可以传参

           function Father(name){

              this.name = name;

              this.colors = ["red", "blue", "green"];

           }

           Father.prototype.sayName=function(){

              console.log(this.name);

           }

           function Son(name,age){

              //构造函数继承

               Father.call(this,name);

              this.age = age;

           }

           //原型链继承

           Son.prototype = new Father();

           var obj = new Son("jike",25);

           console.log(obj);

           obj.sayName();//jike 可以调用父类的原型上的方法

           obj.colors.push("write");

           console.log(obj.colors);// ["red", "blue", "green", "write"]

           var obj2 = new Son("mike",30);

           console.log(obj.colors);//["red", "blue", "green", "write"]

4.原型式继承

//            重点:用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了可以随意增添属性的实力或者对象. object.create()就是这个原理

//            特点:类似于复制一个对象,用函数来包装

//            缺点:1.所有实例都会继承原型上的属性,方法

//                2.无法实现复用.(新实例的属性都是后面添加)

              function content(obj){  //封装一个函数,用来输出对象和承载继承的原型

                  function F(){  //创建一个构造函数,同时会有一个原型产生

                    

                  }

                  F.prototype=obj;  //使其构造函数的原型继承于obj obj为传入的参数,是一个对象

                  return new F();  //返回利用这个函数创造的一个新实例

              }

              var obj = new Object();//obj为一个对象

              obj.name = "jike";//给obj对象一个属性

              obj.colors = ["red","blue"];

              obj.__proto__.age=[1,2,3,4];

              var obj2 = content(obj);//调用继承函数,并将要继承的对象传入到函数里面

              console.log(obj);

              obj2.colors.push("write");

              obj2.age.push(10);

              console.log(obj2);

              console.log(obj2.age);

              console.log(obj);

              var obj3 = Object.create(obj);

              console.log(obj3);

              var obj4 = content(obj);

              console.log(obj4);

//            和原型链继承一样,同样是将自身的对象原型继承一个完整的对象,也可以说是将一个对象作为自身的原型对象,对于引用类型的数据一样继承的是引用地址,那么一个子实例对引用类型的数据进行操作的话,所有实例都会受到影响.

猜你喜欢

转载自www.cnblogs.com/Godfather-twq/p/11494265.html