原型链继承
// 原型链继承
// 父类元素新增原型方法、原型属性,子类都能访问到
// 简单,易于实现
// 缺点:1.无法实现多继承,2.来自原型对象的所有属性被所有子类共享。3.要创建子类实例时,无法向父类构造函数传参
// 4. 要想为子类新增属性和方法,必须要在Student.prototype = new Person() 之后执行,不能放到构造器中
function Person(name, age) {
this.name = name;
this.age = age;
this.play = [1,2,3];
this.setName = function(name) {
this.name = name;
};
}
Person.prototype.setAge = function(age) {
this.age = age;
}
function Student(price) {
this.price = price;
this.setScore = function() {}
}
Student.prototype = new Person();
var s1 = new Student(15000);
var s2 = new Student(14000);
s1.setName('zhuishao');
s1.setAge(24);
console.log(s1, s2);
Student.prototype = new Person() 等价于
Student.prototype.constuctor = Person; Student.prototype.__proto__=Person.prototype 注意:Student.prototype !== Student.prototype.__proto__ 因为他们指向的地址是不同的
借用构造函数继承
// 借用构造函数继承
// 解决了原型链继承中子类实例共享父类引用属性的问题
// 创建子类实例时,可以向父类传递参数
// 可以实现多继承
// 缺点1. 实例不是父类的实例,只是子类的实例 2.只能继承父类的属性和方法,不能继承父类的原型属性和方法
// 3.无法实现函数的复用,每个子类都有父类实例函数的副本,影响性能
function Person(name, age) {
this.name = name;
this.age = age;
this.setName = function() {}
}
Person.prototype.setAge = function() {}
function Student(name, age, price) {
Person.call(this, name, age);
this.price = price
}
var s1 = new Student('Tom', 20, 15000);
原型链+借用构造函数的组合继承
// 原型链+借用构造函数的组合继承
// 可以继承实例属性/方法,也可以继承原型属性/方法
// 不存在引用属性共享问题
// 可传参,函数可复用
function Person(name, age) {
this.name = name;
this.age = age;
this.setName = function() {}
}
Person.prototype.setAge = function(age) {
this.age = age;
}
function Student(name, age, price) {
Person.call(this, name, age);
this.price = price
}
Student.prototype = new Person();
Student.prototype.constructor = Student;
var s1 = new Student('Tom', 20, 15000);
组合继承优化
// 组合继承优化
// 不会初始化两次实例方法/属性,避免的组合继承的缺点
// 缺点:没办法辨别实例时子类还是父类创造的,子类和父类的构造函数指向同一个
function Person(name, age) {
this.nam = name;
this.age = age;
this.setAge = function() {}
}
Person.prototype.setAge = function() {
console.log('111');
};
function Student(name, age, price) {
Person.call(this, name,age);
this.price = price;
this.setScore = function() {}
}
Person.prototype.sayHello = function() {
console.log('hello');
}
Student.prototype = Person.prototype;
var s1 = new Student('Tom', 20, 15000);
console.log(s1);
组合继承优化2,最完美
function Person(name, age) {
this.name = name,
this.age = age
}
Person.prototype.setAge = function () {
console.log("111")
}
function Student(name, age, price) {
Person.call(this, name, age)
this.price = price
this.setScore = function () {}
}
Student.prototype = Object.create(Person.prototype)//核心代码
Student.prototype.constructor = Student//核心代码
var s1 = new Student('Tom', 20, 15000)
console.log(s1 instanceof Student, s1 instanceof Person) // true true
console.log(s1.constructor) //Student
console.log(s1)
注意:Object.create是创建了只包含原型链不包含对象this的一个对象,所以需要Person.call获取对象本身的方法与属性