1、apply();
示例
function Student(name, age, grade) {
Person.apply(this, arguments); // 用apply调用Person,this(Student)代替Person的this,达到继承Person的对象和方法的目的
this.grade = grade;
}
function Person(name, age) {
this.name = name;
this.age = age;
this.type = 'person';
}
var student = new Student("zhangsan", 21, "一年级");
console.log('student:', student.type) // student: person
- 缺点:
1、拿不到父类中prototype中的对方和方法,无论是在调用apply()之前还是之后
2、父类中公有的对象/方法都通过this传递,每new一个实例都需要储存this的内容,耗费内存
测试如下:
function Student(name, age, grade) {
Person.prototype.sex = 'male';
Person.apply(this, arguments); // 用apply调用Person,this(Student)代替Person的this,达到继承Person的所有对象和方法的目的
this.grade = grade;
}
function Person(name, age) {
this.name = name;
this.age = age;
this.type = 'person';
}
Person.prototype.race= 'han';
var student = new Student("zhangsan", 21, "一年级");
console.log('student:', student.type) // student: person
console.log('student sex:', student.sex) // student sex: undefined
console.log('student race:', student.race) // student race: undefined
2、 利用空对象作为中介
示例
function Student(name, age, grade) {
this.grade = grade;
}
function Person(name, age) {
this.name = name;
this.age = age;
}
function extend(Child, Parent) {
var F = function() {}; // 空对象,几乎不占内存。
F.prototype = Parent.prototype; // 空对象的prototype对象指向Parent的prototype,相当于获取了Parent的prototype
Child.prototype = new F(); // Child的prototype对象指向空对象的prototype,间接获取Parent的prototype
Child.prototype.constructor = Child; // 没有这句会造成继承链的紊乱,手动把构造器指回给Child
Child.uber = Parent.prototype; // 为子对象设一个uber属性,这个属性直接指向父对象的prototype属性。这等于在子对象上打开一条通道,可以直接调用父对象的方法。这一行放在这里,只是为了实现继承的完备性,纯属备用性质。
}
Person.prototype.type = 'person';
extend(Student, Person);
var student = new Student("zhangsan", 21, "一年级");
console.log('student type:', student.type); // student type: person
- 公有的内容只能通过prototype来传递,优势就是少new很多this的构造函数,比较节省内存,最大的优势是,子类的prototype发生变化时,不影响父类的prototype
测试如下:
function Student(name, age, grade) {
this.grade = grade;
}
function Person(name, age) {
this.name = name;
this.age = age;
}
function extend(Child, Parent) {
var F = function() {}; // 空对象,几乎不占内存。
F.prototype = Parent.prototype; // 空对象的prototype对象指向Parent的prototype,相当于获取了Parent的prototype
Child.prototype = new F(); // Child的prototype对象指向空对象的prototype,间接获取Parent的prototype
Child.prototype.constructor = Child; // 没有这句会造成继承链的紊乱,手动把构造器指回给Child
Child.uber = Parent.prototype; // 为子对象设一个uber属性,这个属性直接指向父对象的prototype属性。这等于在子对象上打开一条通道,可以直接调用父对象的方法。这一行放在这里,只是为了实现继承的完备性,纯属备用性质。
}
Person.prototype.type = 'person';
extend(Student, Person);
Student.prototype.subType = 'student';
var student = new Student("zhangsan", 21, "一年级");
console.log('student type:', student.type); // student type: person
console.log('student subType:', student.subType); // student subType: student
console.log('Person.prototype:', Person.prototype); // Person.prototype: {type: "person", constructor: ƒ}
3、 拷贝继承
示例
function Student(name, age, grade) {
this.grade = grade;
}
function Person(name, age) {
this.name = name;
this.age = age;
}
function extend2(Child, Parent) {
var p = Parent.prototype;
var c = Child.prototype;
for (var i in p) { // 遍历拷贝赋值
c[i] = p[i];
}
c.uber = p;
}
Person.prototype.type = 'person';
extend2(Student, Person);
Student.prototype.subType = 'student';
var student = new Student("zhangsan", 21, "一年级");
console.log('student type:', student.type); // student type: person
console.log('student subType:', student.subType); // student subType: student
console.log('Person.prototype:', Person.prototype); // Person.prototype: {type: "person", constructor: ƒ}
仅作为学习笔记,有误请指正,玻璃心不接受批评
参考:http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance.html
网友评论