首页 > 技术文章 > 继承(学习笔记) —— 《高级教程》

johnhery 2018-10-19 19:14 原文

继承

原型链

 先不管上图,先来看以下代码:

 
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

 

推荐阅读