js继承的几种方式
1.原型链继承(2星)
简介:原型链是是实现继承的主要方法,其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。
父类 function Father(){ this.property=true } Father.prototype.getSuperValue=function(){ return this.property } 子类 function Son(){ this.subproperty=false } 继承了Father Son.prototype=new Father() const instance =new son() console.log(instance.getSuperValue())//true
优点:实例继承了父类属性和方法
缺点:1.子类无法向父类传递参数
2.所有实例共享父类实例的属性,一个实例修改了原型上的属性,其他实例的原型也会被修改
2.借用构造函数(2星)
简介:为了解决原型中包含引用类型值所带来的问题,开发人员使用了借用构造函数,即在子类构造函数中的内部调用超类构造函数
代码示例:
父类 function Father(){ this.colors=["red","bule","green"] } 子类 function Son(){ // 继承属性 Father.call(this) } var instance1=new Son() instance1.colors.push('black') instance1.colors // "red,buel,green,black" var instaceof2 =new Son() instance2.colors // "red,buel,green"
优点:1.可以在子类中向超类型构造函数中传递参数
2.可以继承多个构造函数的属性(call多个父类对象)
缺点:1.函数复用无从谈起,在超类型中定义的方法,对于子类而言也是不可见的
2.不能继承原型上的属性和方法
3.组合继承(4星)
简介:也叫伪经典继承,指的是将原型链和借用构造函数技术组合到一块,从未发挥二者之长
代码示例:
父类 function Father(name){ this.name=name this.colors=['red','bule','green'] } Father.prototype.sayName=function(){ console.log(this.name) } 子类 function Son(name,age){ // 继承属性 Father.call(this) this.age=age } //继承方法 Son.prototype=new Father() Son.prototype.sayAge=function(){ console.log(this.age) } var instanceof1=new Son('Nicholas',29)
优点:1.结合了2种模式,可以传参可以复用
2.每个实例引入的构造函数属性都是私有的
缺点:无论什么情况下,都会调用两次超类型构造函数,一次是创建子类原型的时候,一次是在子类构造函数内部,影响性能
4.原型式继承(2星)
简介:在函数内部创建创建一个临时性的构造函数,然后将传入的对象作为这个构造函数的原型对象,最后返回一个临时性的新实例,从本质上来讲,object对传入的对象执行了一次浅复制。
代码示例:
function object(obj)( function F(){} F.prototype=obj return new F() } var Person={ name:"Nicholas", friends:['shelby','Court','Van'] } var anotherPerson=object(person) anotherPerson.name='Greg' anotherPerson.push('Rob') console.log(Person.friends) //'shelby','Court','Van',Rob'
优点:类似复制一个对象,用函数来包装
缺点:1.无法实现复用,新的属性都是后面添加的
2.所有实例共享原型上的方法
扩展:ECMAScript5通过新增Object.create() 方法规范了原型式继承
5.寄生式继承(2星)
简介:寄生式继承和工厂模式类似,即创建一个仅用于封装继承过程的函数,该函数内部以某种方式增强对象,最后返回对象
代码示例:
function createAnother (original){ var clone =Object (original) clone.sayHi=function (){ alert("hi") } return clone } var Person={ name:"Nicholas", friends:['shelby','Court','Van'] } var anotherPerson=createAnother(person) anotherPerson.sayHi() //hi
优点:有person对象的属性和自己的sayHI方法
缺点:不能做到函数复用,这一点与构造函数类似
6.寄生式组合继承(5星)
简介:本质是使用寄生式来继承超类型的原型,然后将结果指定给子类的原型
代码示例:
function inheritPrototype (Son,Father){ var prototype =Object(Father.prototype) //创建对象 prototype.constructor=Son//增强对象 son.protoype=prototype //指定对象 } function Father(name){ this.name=name this.colors=['red','bule','green'] } Father.prototype.sayName=function(){ console.log(this.name) } function Son(name,age){ // 继承属性 SuperType.call(this) this.age=age } inheritPrototype(Son,Father) Son.prototype.sayAge=function(){ alert(this.age) }
优点:最理想的继承方式,修复了组合继承2次调用超类的问题
6.ES6通过extends实现类的继承(推荐)
简介:class的本质是一个function,它可以看作一个语法糖,让对象原型的写法更加清晰,更像面向对象的编程语法
父类 class Father { constructor(a,b){ this.a=a this.b=b } hello (){ console.log(this.a) } } 子类 class Child extends Father{ constructor(a,b,c){ super(a,b) //调用父类的constructor(a,b) this.c=c } } const cp=new Child(1,2,3) cp instanceof Child //true cp instanceof Father //true cp.hello() // 1