下面是关于“JS精髓原型链继承及构造函数继承问题纠正”的完整攻略。
原型链继承
在JavaScript中,对象可以通过原型链进行继承。原型链是一个对象到另一个对象的链,每个对象都有一个指向它的原型对象的引用。
实现原型链继承
示例代码如下:
function Animal() {
this.name = 'animal';
this.showName = function () {
console.log(this.name);
}
}
function Cat() {
this.name = 'cat';
this.color = 'black';
}
Cat.prototype = new Animal();
var cat = new Cat();
cat.showName(); // 'cat'
console.log(cat.color); // 'black'
console.log(cat instanceof Cat); // true
console.log(cat instanceof Animal); // true
在上述代码中,我们先定义了一个Animal
类,它有一个name
属性和一个showName
方法。然后我们定义了一个Cat
类,它有一个name
和一个color
属性。接下来通过修改Cat.prototype
属性来让它继承Animal
类,最后实例化一个Cat
对象,此时这个对象既属于Cat
类,也属于Animal
类。
原型链继承的问题
原型链继承虽然很方便,但是会存在一些问题:
- 引用类型的属性被所有实例共享
- 在创建 Child 的实例时,无法向 Parent 传参
- 解决了原型链继承中一个实例修改属性附带到了类原型上的问题,但是实例化的时候还是要执行 父类的构造函数,只是在父类构造函数执行完之后,再把子类的属性再次进行了一遍覆盖而已。
构造函数继承
除了原型链继承,还可以使用构造函数继承,即在子类的构造函数中调用父类的构造函数,并为其传递参数,这样子类的实例就可以拥有父类的属性。
实现构造函数继承
示例代码如下:
function Animal(name) {
this.name = name;
this.showName = function () {
console.log(this.name);
}
}
function Cat(name) {
Animal.call(this, name);
this.color = 'white';
}
var cat = new Cat('cat');
cat.showName(); // 'cat'
console.log(cat.color); // 'white'
console.log(cat instanceof Cat); // true
console.log(cat instanceof Animal); // false
在上述代码中,我们定义了一个Animal
类,它有一个name
属性和一个showName
方法。然后我们定义了一个Cat
类,它继承自Animal
类,并在构造函数中通过Animal.call(this, name)
来调用父类的构造函数,并为其传递参数。最后实例化一个Cat
对象,此时这个对象只属于Cat
类,不属于Animal
类。
构造函数继承的问题
构造函数继承虽然解决了原型链继承中属性共享的问题,但是也存在一些问题:
- 没有办法实现函数的复用,每个子类都会有父类中同名的函数,导致浪费内存。
- 只能继承父类的实例属性和方法,不能继承原型属性和方法。
原型链 + 构造函数组合继承
针对上述两种继承方式的问题,常见的继承方式是原型链 + 构造函数组合继承。
实现原型链和构造函数组合继承
示例代码如下:
function Animal(name) {
this.name = name;
this.friends = ['Tom', 'Jerry'];
}
Animal.prototype.showName = function () {
console.log(this.name);
}
function Cat(name) {
Animal.call(this, name);
this.color = 'white';
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
var cat = new Cat('cat');
cat.showName(); // 'cat'
console.log(cat.color); // 'white'
console.log(cat.friends); // ['Tom', 'Jerry']
var cat2 = new Cat('cat2');
cat2.friends.push('Jack');
console.log(cat.friends); // ['Tom', 'Jerry']
console.log(cat2.friends); // ['Tom', 'Jerry', 'Jack']
在上述代码中,我们先定义了一个Animal
类,它有一个name
属性和一个friends
属性,showName
方法定义在了原型上。然后我们定义了一个Cat
类,它通过Animal.call(this, name)
来调用父类的构造函数,并为其传递参数。接着通过Cat.prototype = new Animal();
和Cat.prototype.constructor = Cat;
来将Cat
类的原型设置为Animal
的实例,并将constructor
指向Cat
类。最后实例化一个Cat
对象,此时这个对象既属于Cat
类,也属于Animal
类。
原型链和构造函数组合继承的优点
原型链和构造函数组合继承可以解决上述两种继承方式的问题:
- 实现函数的复用,同名函数只会存在于原型链上,不会占用多余的内存。
- 子类既继承了父类的实例,也继承了父类的原型属性和方法。
至此,我们介绍完了JS精髓原型链继承及构造函数继承问题纠正的攻略,希望对您有所帮助。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JS精髓原型链继承及构造函数继承问题纠正 - Python技术站