ES5继承、ES5继承与ES6的区别

本文深入解析JavaScript中的五种继承方式:构造函数继承、原型链继承、组合继承、寄生组合继承及ES6类继承。详细对比了每种方式的特点、优缺点,并探讨了ES6继承与ES5继承的关键区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

每一个构造函数都有prototype属性 (是属性),这个prototype属性会指向一个对象,这个对象就是原型,然后每一个原型对象都会有一个constructor属性,指向它的构造函数。通常来说Person.prototype.constructor=Person。
原型链:每一个对象都有一个__proto__(dunder)属性,(obj.proto==Function.prototype),实例对象的__proto__属性所指向的对象,等于其构造函数的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, this.age)
}
function Child (sex,name,age) {
    this.sex = sex
    Person.call(this,name,age)
}
Child.prototype = new Person();
//或者Child.prototype = Object.create(Person.prototype),这两条语句的效果是一样的,都使得 Child.prototype.__proto__==Person.prototype 为true
/* 重新设置一下constructor 不设置也没有影响,严谨的角度上来说还是设置一下*/
/* 不设置的话,__proto__ 上时没有 constructor */
/* 正常来讲constructor是指向自身的 */
child.prototype.constructor = child;
let p1 = new child('man','czklove','13')
let p2 = new child('man','czklove1','16')
p1.sayholle(); // czklove 13

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

寄生组合继承

寄生组合继承是,让子类型的原型对象等于父类型的原型对象的副本。优点:解决了组合继承的缺点,避免了在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
}
  var prototype = Object(Parent.prototype)
  prototype.constructor = Child
  Child.prototype= prototype
var child = new Child('Child', 18)

ES6类继承与ES5继承的区别?

ES6使用语法 class B extends A继承,ES6类继承是ES5函数继承的语法糖,把ES6的继承通过Babel转义成ES5之后,发现它是通过object.create方法实现了(1)B.proto = A。表示子类B继承父类A的静态属性。通过Object.setPropertypeOf()方法实现(2)B.prototype.proto = A.prototype 。这与组合继承相同。 (一) ES6继承同时存在两条继承链。ES5是没有第一条原型链的。
(二) ES6的子类必须在constructor方法中调用super()方法,super()代表调用父类的构造函数,因为子类没有自己的this对象,所以子类要先继承父类的this。但ES5 的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this))。
(三) ES6 可以自定义原生数据结构(比如Array、String等)的子类,这是 ES5 无法做到的。

class A {
}

class B {
}

// B 的实例继承 A 的实例
Object.setPrototypeOf(B.prototype, A.prototype);

// B 继承 A 的静态属性
Object.setPrototypeOf(B, A);

const b = new B();
Object.setPrototypeOf = function (obj, proto) {
  obj.__proto__ = proto;
  return obj;
}
Object.setPrototypeOf(B.prototype, A.prototype);
// 等同于
B.prototype.__proto__ = A.prototype;

Object.setPrototypeOf(B, A);
// 等同于
B.__proto__ = A;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值