构造函数式继承
function People(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
// 方法要写在原型上
People.prototype.say = function () {
console.log("大家好我的名字叫做" + this.name);
}
// 定义子类
function Student(name, age, sex, grade) {
// 构造函数式继承
People.apply(this, arguments);
this.grade = grade;
}
var s = new Student("小明", 12, "男", 6);
console.log(s);
console.log(s instanceof People);
结果:
结论:构造函数式继承只能继承属性。
类式继承(原型式继承)
// 定义父类
function People(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
// 方法要写在原型上
People.prototype.say = function () {
console.log("大家好我的名字叫做" + this.name);
}
// 定义子类
function Student(name, age, sex, grade) {
this.grade = grade;
}
//让子类的原型指向父类的实例
Student.prototype = new People();
//类式继承会丢失构造器属性,需手工补回
Student.prototype.constructor = Student;
var s = new Student("小明", 12, "男", 6);
console.log(s);
console.log(s instanceof Student);
console.log(s instanceof People);
结果:
结论:类式继承只能继承方法。注:s中没有say方法,再去s的原型中查找,也就是父类的实例中查找,父类的实例中也没有say方法,但父类的实例的原型上有say方法。
组合式继承
构造函数式继承+类式继承
// 定义父类
function People(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
// 方法要写在原型上
People.prototype.say = function () {
console.log("大家好我的名字叫做" + this.name);
}
// 定义子类
function Student(name, age, sex, grade) {
//构造函数式继承
People.apply(this, arguments);
this.grade = grade;
}
//让子类的原型指向父类的实例
Student.prototype = new People();
//类式继承会丢失构造器属性,需手工补回
Student.prototype.constructor = Student;
var s = new Student("小明", 12, "男", 6);
console.log(s);
console.log(s instanceof Student);
console.log(s instanceof People);
结果:
结论:组合式继承既能继承属性,又能继承方法。但是s的原型上有很多值为undefined的多余属性。
Object.create
// 定义父类
function People(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
// 方法要写在原型上
People.prototype.say = function () {
console.log("大家好我的名字叫做" + this.name);
}
// 定义子类
function Student(name, age, sex, grade) {
//构造函数式继承
People.apply(this, arguments);
this.grade = grade;
}
// 使用Object.create
Student.prototype = Object.create(People.prototype);
// 实例化子类
var s = new Student("小明", 12, "男", 6);
console.log(s);
console.log(s instanceof People);
console.log(Student.prototype);
console.log(Student.prototype.__proto__ === People.prototype);
结果:
Object.create()相当于新建一个对象,然后让这个新对象的隐式原型指向括号内的第一个参数对象,这里也就是父类的原型。
也就是相当于:
var obj = {};
obj.__proto__ = People.prototype;
Student.prototype = obj;
Object.create方法的实现
Object.create = function (prototype) {
var F = function () {
}
F.prototype = prototype;
return new F();
}
因为在ES6之前__proto__不是标准属性,IE之前不支持,IE11开始支持了。可以使用标准属性Object.getPrototypeOf(obj)代替。