继承
原型链
先不管上图,先来看以下代码:
function Person() { this.personName = 'person'; } Person.prototype.sayPersonName = function() { console.log(this.personName); } function Student() { this.studentName = 'student'; } Student.prototype = new Person(); // Student 的原型对象替换为 Person 的实例对象 参考上图中右边第一条红线 Student.prototype.sayStudentName = function() { console.log(this.studentName); } var student1 = new Student(); student1.sayPersonName(); // person student1.sayStudentName(); // student
结合代码和上图,可以清楚得看到,将某个构造函数的原型对象替换为另一个构造函数的实例对象后,最终的指向(图中红线部分,就像链条一样,层层链接)。这就是原型链的基本概念。
coding:
1 function Myarray(){ 2 this.name = 'myarray'; 3 } 4 5 Myarray.prototype = new Array(); 6 7 var arr1 = new Myarray(); 8 9 console.log(arr1.name); 10 11 arr1.unshift(3); 12 arr1.unshift(2); 13 arr1.unshift(4); 14 arr1.push(5); 15 arr1.sort(); 16 17 console.log(arr1 instanceof Array);; 18 arr1.forEach( 19 function(ele,index){ 20 console.log(index+":"+ele); 21 } 22 )
默认的原型
所有引用类型默认都继承了 Object,这也是通过原型链实现的。
确定原型和实例的关系
- instanceof
- isPrototypeOf()
instanceof
console.log(student1 instanceof Student); // true console.log(student1 instanceof Person); // true console.log(student1 instanceof Object); // true
student1 是 Student, Person, Object 三者中任意一个类型的实例。
isPrototypeOf()
console.log(Student.prototype.isPrototypeOf(student1)); // true console.log(Person.prototype.isPrototypeOf(student1)); // true console.log(Object.prototype.isPrototypeOf(student1)); // true
借用构造函数(constructor stealing)
在子类型构造函数的内部借用超类型构造函数。
function Person() { this.friends = ['Mike', 'Lily', 'Melinda']; } function Student() { Person.call(this); // 调用一遍 Person 构造函数,在新 Student 对象上执行 Person 函数中定义的所有对象初始化代码,每个实例都会有自己的属性的副本 } var student1 = new Student(); student1.friends.push('Lucy'); console.log(student1.friends); // ["Mike", "Lily", "Melinda", "Lucy"] var student2 = new Student(); console.log(student2.friends); // ["Mike", "Lily", "Melinda"]
优点:可以传递参数。
function Person(name) { // <-- 参数 this.friends = ['Mike', 'Lily', 'Melinda']; this.name = name; } function Student(name) { Person.call(this, name); // <-- 传入参数 } var student1 = new Student('John'); console.log(student1.name); // John var student2 = new Student('Gray'); console.log(student2.name); // Gray
缺点
- 方法都在构造函数中定义,无法实现方法复用
- 在超类型的原型中定义的方法,子类型不可见
组合继承(combination inheritance)
原型链和借用构造函数的组合
function Person(name) { this.name = name; } Person.prototype.sayName = function() { console.log(this.name); } function Student(name, age) { Person.call(this, name); this.age = age; } Student.prototype = new Person(); Student.prototype.constructor = Student; Student.prototype.sayAge = function() { console.log(this.age); } var student1 = new Student('Mike', 28); student1.sayName(); // Mike student1.sayAge(); // 28
原型式继承(prototypal inheritance)
借助原型基于已有的对象创建新对象。
function object(obj) { function fn() { } fn.prototype = obj; return new fn(); } var obj = { name: 'Miker', sayName: function() { console.log(this.name); } } var newObj = object(obj); newObj.name = 'John'; console.log(newObj.name); // John newObj.sayName(); // John
或
Object.create(obj, {});
寄生式继承(parasitic)
function createAnother(original) { var clone = object(original); // <-- 调用原型式继承的方法 clone.sayHi = function() { // <-- 增强这个对象 console.log('Hi'); } return clone; // 返回这个对象 }
寄生组合式继承
组合继承的缺点:调用两次超类型构造函数。
function Person(name) { this.name = name; } Person.prototype.sayName = function() { console.log(this.name); } function Student(name, age) { Person.call(this, name); // <-- 第二次调用超类型构造函数 this.age = age; } Student.prototype = new Person(); // <-- 第一次调用超类型构造函数 Student.prototype.constructor = Student; Student.prototype.sayAge = function() { console.log(this.age); }
改造:
function object(obj) { function fn() { } fn.prototype = obj; return new fn(); } function inheritPrototype(subType, superType) { // <-- 原型继承 var prototype = object(superType.prototype); // 原型对象 prototype.constructor = subType; subType.prototype = prototype; } function Person(name) { this.name = name; } Person.prototype.sayName = function() { console.log(this.name); } function Student(name, age) { Person.call(this, name); this.age = age; } inheritPrototype(Student, Person); Student.prototype.sayAge = function() { console.log(this.age); } var student1 = new Student('Mike', 28);
画了一张关系图,仅供参考
以上内容转自:http://www.cnblogs.com/lwl0812/p/9818192.html