1. 程式人生 > >繼承(學習筆記) —— 《高級教程》

繼承(學習筆記) —— 《高級教程》

內部 name nbsp pan 返回 ima 初始 圖片 筆記

繼承

技術分享圖片

原型鏈

技術分享圖片

先不管上圖,先來看以下代碼:

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

結合代碼和上圖,可以清楚得看到,將某個構造函數的原型對象替換為另一個構造函數的實例對象後,最終的指向(圖中紅線部分,就像鏈條一樣,層層鏈接)。這就是原型鏈的基本概念。

默認的原型

所有引用類型默認都繼承了 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);

畫了一張關系圖,僅供參考

技術分享圖片

有理解的不對的地方,煩請指出,謝謝!!

註:以上所有的文字、代碼都是本人一個字一個字敲上去的,圖片也是一張一張畫出來的,轉載請註明出處,謝謝!

繼承(學習筆記) —— 《高級教程》