1.使用call实现继承(不推荐)
function Animal(name) {this.name = name;this.run = function() {console.log(this.name, "跑");}
}
function Dog(name) {// 继承Animal.call(this, name);this.sleep = function() {console.log(this.name, "睡");}
}
dog = new Dog("旺财");
dog.run(); // 旺财 跑
dog.sleep(); // 旺财 睡
(1)优点
- 父类的构造函数在子类构造函数中调用,可以向父类构造函数传递参数;
- 子类实例化后,不会受到父类实例化后修改属性的影响。
(2)缺点
- 子类实例无法通过instanceof判断出父类的实例;
- 无法继承父类原型链上的属性和方法,只能继承父类的实例属性和方法;
- 子类实例无法通过instanceof判断出父类的实例;
2.使用原型实现继承(不推荐)
function Animal(){this.run = function() {console.log(this.name, "跑");}
}
function Dog(name){this.name = name;this.sleep = function() {console.log(this.name, "睡");}
}
// 继承
Dog.prototype = new Animal();dog = new Dog("大黄");
dog.sleep(); // 大黄 睡
dog.run(); // 大黄 跑
优点:
- 子类实例可以通过instanceof判断出父类的实例;
- 每个子类实例共享父类的属性和方法,节省内存。
缺点:
- 无法继承父类原型链上的属性和方法,只能继承父类的实例属性和方法;
- 子类实例共享父类的属性和方法时,如果修改了属性值,其他实例也会受到影响;
- 无法传递参数给父类的构造函数,父类的属性只能通过子类的构造函数传递。
3.上述两种方法结合(推荐)
// 1.定义一个父类
function Animal(name) {this.name = name;
}// 2.定义父类的原型方法
Animal.prototype.speak = function() {console.log(this.name + ' makes a noise.');
};// 3.定义一个子类
function Dog(name, breed) {Animal.call(this, name); // 调用父类的构造函数this.breed = breed;
}// 4,将子类的原型设置为父类的一个实例,实现继承
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;// 5.定义子类的原型方法
Dog.prototype.bark = function() {console.log(this.name + ' barks.');
};// 创建一个Dog对象并调用其方法
var myDog = new Dog('Buddy', 'Labrador');
myDog.speak(); // Buddy makes a noise.
myDog.bark(); // Buddy barks.
优点:
- 子类实例可以通过instanceof判断出父类的实例;
- 子类即拥有父类构造函数中的属性和方法,也有父类prototype中的属性和方法;