欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ES5继承

程序员文章站 2022-07-15 20:30:37
...

原型链:每一个构造含函数都有prototype属性 (是属性),这个prototype属性会指向一个对象,这个对象就是原型,然后每一个原型对象都会有一个constructor属性,指向它的构造函数,这样就形成了一种链式结构。并且每一个对象都有一个__protp__(dunder)属性,(obj.proto==Function.prototype),当我们访问一个对象的属性或方法时,如果这个对象没有这个属性或方法,就会顺着原型链向上查找。

一、构造函数继承

重点:用.call()和.apply()将父类构造函数引入子类函数(在子类函数中做了父类函数的自执行)
    特点:1、只继承了父类构造函数的属性,没有继承父类原型的属性。
       2、解决了原型链继承缺点1、2、3。
       3、可以继承多个构造函数属性(call多个)。
       4、在子实例中可向父实例传参。
    缺点:1、只能继承父类构造函数的属性,不能继承父类原型上的属性。
       2、因为不能继承父类原型链上的方法,所有要继承的函数只能定义在父类构造函数上,无法实现构造函数的复用。(每次 用每次都要重新调用)
       3、每个新实例都有父类构造函数的副本,臃肿。

function person (name,age) {
    this.name = name
    this.age = age
    this.test =function(){ console.log('test')}
}
person.prototype.sayholle = function () {
    console.log(this.name+' holle'+ this.age)
}
function child (sex,name,age) {
    this.sex = sex
    person.call(this,name,age)
}

let p1 = new child('woman','rose','13')
let p2 = new child('man','jack','13')
console.log(p1.test===p2.test) //false  这是函数方法不能复用的意思

二、原型链继承

让子类构造函数的prototype指向父类的实例对象

function Parent2() {
                this.name = 'parent2';
                this.play = [1, 2, 3];
            }
            function Child2(age) {
                this.age = age;
            }
            Child2.prototype = new Parent2();//new Child2().__proto__===Child2.prototype
            var s1 = new Child2();
            var s2 = new Child2();
            console.log(s1.play, s2.play);//(3) [1, 2, 3] (3) [1, 2, 3]
            s1.play.push(4);
            console.log(s1.play, s2.play);//(4) [1, 2, 3, 4] (4) [1, 2, 3, 4]

特点:1、实例可继承的属性有:子类、父类构造函数的属性,子类、父类原型的属性。
    缺点:1、新实例无法向父类构造函数传参。
       2、不能多继承。
       3、所有新实例都会共享父类构造函数中的属性,一个实例修改了属性,其他实例的属性也会改变。(但是子类构造函数中的属性是独立的)

三、组合继承

function person (name,age) {
    this.name = name
    this.age = age
}
person.prototype.sayholle = function () {
    console.log(this.name+' holle'+ this.age)
}
function child (sex,name,age) {
    this.sex = sex
    person.call(this,name,age)
}
child.prototype = new person();
/* 重新设置一下constructor 不设置也没有影响,严谨的角度上来说还是设置一下*/
/* 不设置的话,__proto__ 上时没有 constructor */
/* 正常来讲constructor是指向自身的 */
child.prototype.constructor = child;
let p = new child('man','czklove','13')
let p1 = new child('man','czklove1','16')
p.sayholle(); // czklove holle13

特点:组合继承,既能达到对父类属性的继承,也能继承父类原型上的方法,父类属性继承也不会在所有子类的实列上共享。
唯一缺点,子类原型上有父类构造函数的属性,也就是多了一份属性

寄生组合继承

寄生组合的方式是改进组合继承,其实也是ES6的class的实现方式???
基本思想:通过借用构造函数来继承属性,通过原型链的混成形式来继承方法(这个和组合继承的思想一样)。本质上,即通过借助构造函数来继承属性,通过使用子类型的原型继承父类型的原型来继承方法。
优点:解决了组合继承的缺点,避免了在subtype.prototype上创建不必要的,多余的属性(也就是组合继承中,父类构造器中的属性,不会被添加到原型上),与此同时,原型链还能保持不变,因此,寄生组合式继承被认为是引用类型最理想的继承范式。

function Parent(name) {
  this.name = name
}
 
Parent.prototype.sayName = function() {
	console.log('my name is ' + this.name)
	return this.name
} 
function Child(name, age) {
	Parent.call(this, name)
	this.age = age
}
 
function _inherits(Child, Parent) {
  Child.prototype = Object.create(Parent.prototype)
  Child.prototype.constructor = Child
  Child.__proto__ = Parent
 
}
_inherits(Child, Parent)

var child = new Child('Child', 18)

相关标签: JS

上一篇: Es5继承

下一篇: 命令模式第二篇