一、原型链基础
JavaScript的原型链是一种从对象到另一个对象的委托关系。它在一个对象的属性找不到时,会沿着原型链往上找指定名称的属性或方法。我们来看一个例子:
function Animal(name){
this.name = name;
}
Animal.prototype.getName = function(){
return this.name;
}
function Dog(name){
this.name = name;
}
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;
var dog = new Dog('Henry');
console.log(dog.getName()); //输出:Henry
在此代码中,我们定义了Animal和Dog两个构造函数,并且让Dog的原型指向Animal的实例。当我们调用dog.getName()时,JavaScript引擎会在dog对象上查找getName方法,没有找到时会沿着原型链往上找Animal.prototype上的getName方法。
二、改变原型链
在上一个例子中,我们让Dog的原型指向了Animal的实例,在Dog.prototype上定义getName方法。这种方式同样有一些问题:
function Animal(name){
this.name = name;
}
Animal.prototype.getName = function(){
return this.name;
}
function Dog(name){
this.name = name;
}
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;
Dog.prototype.getName = function(){
return 'My name is ' + this.name;
}
var dog = new Dog('Henry');
console.log(dog.getName()); //输出:My name is Henry
var animal = new Animal('Oscar');
console.log(animal.getName()); //输出:Oscar
在此代码中,我们在Dog.prototype上定义了一个新的getName方法,这会影响到它的父对象Animal.prototype上的getName方法,而且animal对象也会受到影响。
为了避免这种相互污染的问题,我们可以使用Object.create()方法,创建一个新的对象作为原型,并将其赋值给Dog.prototype。
function Animal(name){
this.name = name;
}
Animal.prototype.getName = function(){
return this.name;
}
function Dog(name){
this.name = name;
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.getName = function(){
return 'My name is ' + this.name;
}
var dog = new Dog('Henry');
console.log(dog.getName()); //输出:My name is Henry
var animal = new Animal('Oscar');
console.log(animal.getName()); //输出:Oscar
三、继承的多种方式
除了使用原型链实现继承之外,我们还可以使用其他几种方式:构造函数、组合继承、寄生构造函数和组合继承。
1. 构造函数
构造函数是最基本的一种继承方式。它有一些局限性,例如无法访问父对象的属性和方法,但在一些情况下,由于其简单易用,还是有着很大的用武之地。
function Animal(name){
this.name = name;
this.getName = function(){
return this.name;
}
}
function Dog(name, type){
this.type = type;
this.getType = function(){
return this.type;
}
Animal.call(this, name);
}
var dog = new Dog('Henry', 'Poodle');
console.log(dog.getName()); //输出:Henry
console.log(dog.getType()); //输出:Poodle
2. 组合继承
组合继承是指同时采用构造函数和原型链的继承方式。使用该方法,可以避免构造函数和原型链各自的局限性和缺陷。
function Animal(name){
this.name = name;
}
Animal.prototype.getName = function(){
return this.name;
}
function Dog(name, type){
this.type = type;
Animal.call(this, name);
}
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;
Dog.prototype.getType = function(){
return this.type;
}
var dog = new Dog('Henry', 'Poodle');
console.log(dog.getName()); //输出:Henry
console.log(dog.getType()); //输出:Poodle
3. 寄生构造函数
寄生构造函数是指在另一个构造函数的基础上增加一些方法或属性,从而达到继承的目的。与传统的构造函数继承相比,寄生构造函数继承的优势在于可以使用闭包,对属性和方法进行封装,从而达到不污染父对象的目的。
function Animal(name){
this.name = name;
}
Animal.prototype.getName = function(){
return this.name;
}
function Dog(name, type){
var self = new Animal(name);
self.type = type;
self.getType = function(){
return this.type;
}
return self;
}
var dog = new Dog('Henry', 'Poodle');
console.log(dog.getName()); //输出:Henry
console.log(dog.getType()); //输出:Poodle
4. 组合继承
寄生组合继承也是一种很好的继承方式,它通过借用构造函数继承父对象的属性和方法,和通过原型链继承父对象的原型,达到继承的目的。
function Animal(name){
this.name = name;
}
Animal.prototype.getName = function(){
return this.name;
}
function Dog(name, type){
Animal.call(this, name);
this.type = type;
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.getType = function(){
return this.type;
}
var dog = new Dog('Henry', 'Poodle');
console.log(dog.getName()); //输出:Henry
console.log(dog.getType()); //输出:Poodle
原创文章,作者:TEFJL,如若转载,请注明出处:https://www.506064.com/n/368435.html
微信扫一扫
支付宝扫一扫