继承有六种方法:原型链继承,构造函数继承,组合继承,原型式继承,寄生式继承,寄生组合式继承
原型链继承
原型链继承是一种继承方式,它是基于JavaScript中的原型链机制实现的。在JavaScript中,每个对象都有一个原型对象,原型对象又有自己的原型对象,直到达到顶层的Object.prototype。当我们访问一个对象的属性或方法时,如果对象本身没有这个属性或方法,JavaScript就会沿着对象的原型链向上查找,直到找到为止。
原型链继承的实现方式是,让一个对象的原型指向另一个对象,从而继承另一个对象的属性和方法。具体实现如下:
function Parent() { this.name = 'parent'; } Parent.prototype.sayHello = function () { console.log('Hello, ' + this.name); }; function Child() {} Child.prototype = new Parent(); var child = new Child(); child.name = 'child'; child.sayHello(); // 输出 "Hello, child"
在上面的例子中,我们定义了一个Parent构造函数和一个Child构造函数。Child构造函数的原型指向了一个Parent实例,从而继承了Parent的属性和方法。当我们创建Child实例时,它会沿着原型链找到Parent的sayHello方法,并执行它。
需要注意的是,原型链继承有一些缺点。首先,它会将父类的属性和方法全部继承下来,包括一些不需要的属性和方法,这会导致子类实例的属性和方法过多,影响性能。其次,父类的属性如果是引用类型,子类实例修改这个属性会影响到其他实例。因此,原型链继承在实际开发中并不常用,通常使用组合继承或者寄生组合继承。
构造函数继承
构造函数继承是一种继承方式,它是通过在子类构造函数中调用父类构造函数来实现的。在构造函数中,通过使用call或apply方法来改变函数执行时的上下文,从而将父类的属性和方法赋值给子类。具体实现如下:
function Parent(name) { this.name = name; } Parent.prototype.sayHello = function () { console.log('Hello, ' + this.name); }; function Child(name) { Parent.call(this, name); } var child = new Child('child'); child.sayHello(); // 报错,sayHello方法不存在
在上面的例子中,我们定义了一个Parent构造函数和一个Child构造函数。Child构造函数通过调用Parent构造函数,将父类的属性和方法赋值给子类。当我们创建Child实例时,它只继承了父类的属性,而没有继承父类的原型上的方法。因此,调用child.sayHello()会报错。
为了解决这个问题,我们可以将父类的原型对象赋值给子类的原型对象,从而让子类继承父类的原型上的方法。具体实现如下:
function Parent(name) { this.name = name; } Parent.prototype.sayHello = function () { console.log('Hello, ' + this.name); }; function Child(name) { Parent.call(this, name); } Child.prototype = new Parent(); var child = new Child('child'); child.sayHello(); // 输出 "Hello, child"
在上面的例子中,我们将父类的原型对象赋值给子类的原型对象,从而让子类继承了父类的原型上的方法。当我们创建Child实例时,它沿着原型链找到了Parent的sayHello方法,并执行它。
需要注意的是,构造函数继承也有一些缺点。首先,父类的属性和方法只能通过构造函数继承,不能通过原型链继承。其次,每个子类实例都会创建一个新的父类实例,导致内存浪费。因此,构造函数继承在实际开发中也不常用,通常使用组合继承或者寄生组合继承。
组合继承
组合继承是一种继承方式,它是将原型链继承和构造函数继承结合起来的一种方式。组合继承通过在子类构造函数中调用父类构造函数,从而继承父类的属性,同时将父类的原型对象赋值给子类的原型对象,从而继承父类的原型上的方法。具体实现如下:
function Parent(name) { this.name = name; } Parent.prototype.sayHello = function () { console.log('Hello, ' + this.name); }; function Child(name) { Parent.call(this, name); } Child.prototype = new Parent(); Child.prototype.constructor = Child; var child = new Child('child'); child.sayHello(); // 输出 "Hello, child"
在上面的例子中,我们定义了一个Parent构造函数和一个Child构造函数。Child构造函数通过调用Parent构造函数,将父类的属性赋值给子类。同时,我们将父类的原型对象赋值给子类的原型对象,并将子类原型对象的constructor属性指向Child构造函数,从而继承了父类的原型上的方法。
组合继承的优点是比较完备地解决了继承问题,既可以继承父类的属性,也可以继承父类的原型上的方法。缺点是在创建子类实例时,会调用两次父类构造函数,导致内存浪费。因此,后来又出现了一种优化的继承方式,即寄生组合继承。
寄生式继承
寄生式继承是一种继承方式,它是在组合继承的基础上进行优化的一种方式。寄生式继承通过创建一个临时的构造函数,将父类的原型对象赋值给这个构造函数的原型对象,从而继承父类的原型上的方法。具体实现如下:
function Parent(name) { this.name = name; } Parent.prototype.sayHello = function () { console.log('Hello, ' + this.name); }; function Child(name) { Parent.call(this, name); } function inheritPrototype(child, parent) { var prototype = Object.create(parent.prototype); prototype.constructor = child; child.prototype = prototype; } inheritPrototype(Child, Parent); var child = new Child('child'); child.sayHello(); // 输出 "Hello, child"
在上面的例子中,我们定义了一个Parent构造函数和一个Child构造函数。我们通过创建一个临时的构造函数inheritPrototype,将父类的原型对象赋值给子类的原型对象,并将子类原型对象的constructor属性指向Child构造函数,从而继承了父类的原型上的方法。
寄生式继承的优点是解决了组合继承的内存浪费问题,但缺点是代码比较复杂,可读性较差。因此,在实际开发中,我们可以使用ES6中的class关键字来实现继承,它更加简洁明了。
原型式继承
原型式继承是一种基于原型链的继承方式,在 JavaScript 中被广泛使用。它是通过创建一个新的对象,将一个已有的对象作为其原型,并向新对象添加新属性和方法来实现的。
在原型式继承中,我们可以通过 Object.create() 方法来创建一个新对象,并将其原型指向另一个对象。例如,我们可以通过以下代码创建一个新对象,其原型为一个已有的对象:
var parent = { name: 'Parent', sayHello: function() { console.log('Hello, my name is ' + this.name); } }; var child = Object.create(parent);
在上面的代码中,我们首先定义了一个名为 parent 的对象,它有一个 name 属性和一个 sayHello 方法。然后,我们通过 Object.create() 方法创建了一个新对象 child,并将其原型指向 parent 对象。
现在,我们可以通过 child 对象访问 parent 对象的属性和方法,例如:
child.name; // 'Parent' child.sayHello(); // 'Hello, my name is Parent'
我们还可以在 child 对象上添加新属性和方法,例如:
child.age = 10; child.sayAge = function() { console.log('I am ' + this.age + ' years old.'); }; child.sayAge(); // 'I am 10 years old.'
在上面的代码中,我们向 child 对象添加了一个 age 属性和一个 sayAge 方法,并在 sayAge 方法中使用了 this 关键字来引用 child 对象。
需要注意的是,虽然原型式继承可以实现对象之间的继承关系,但它也有一定的缺点。由于原型链的存在,如果我们在子对象上修改了某个属性或方法,那么它会影响到其所有的父对象和兄弟对象。因此,在使用原型式继承时需要小心谨慎,避免出现意想不到的问题。
寄生组合式继承
寄生式继承是一种基于原型式继承的模式,它的思路是创建一个仅用于封装继承过程的函数,该函数在内部以某种方式增强对象,最后返回这个对象。
在 JavaScript 中,我们可以使用寄生式继承来实现对象的继承关系。在寄生式继承中,我们首先创建一个用于封装继承过程的函数,然后在函数内部创建一个新对象,并将其原型指向另一个对象。接着,在函数内部可以对新对象添加新属性和方法,最后返回这个新对象。
以下是一个示例代码:
function createChild(parent) { var child = Object.create(parent); child.sayHello = function() { console.log('Hello, my name is ' + this.name); }; return child; } var parent = { name: 'Parent', }; var child = createChild(parent); child.name = 'Child'; child.sayHello(); // 'Hello, my name is Child'
在上面的代码中,我们首先定义了一个名为 createChild 的函数,它接受一个父对象作为参数,并返回一个新对象。在函数内部,我们使用 Object.create() 方法创建一个新对象 child,并将其原型指向 parent 对象。接着,我们在 child 对象上添加了一个 sayHello 方法,并在方法中使用 this 关键字来引用 child 对象。最后,我们将 child 对象返回。
需要注意的是,虽然寄生式继承可以实现对象之间的继承关系,但它也有一定的缺点。由于它的继承方式是基于原型式继承的,因此也存在原型链的问题。另外,它也会带来一些性能上的损失。因此,在实际开发中需要根据具体情况来选择合适的继承方式。
标签:name,Parent,继承,原型,child,构造函数 From: https://www.cnblogs.com/hgng/p/17297420.html