week 17

面向對象編程

傳統的基於class的面嚮對象語言如Java中,都有兩個基本概念:編程

  • 類:類是對象的實例模版,自己是一種類型。如:
  • 實例:實例是根據類建立的對象。Student xiaoming = new Student()

而JS不區分類和實例的概念,它經過原型(prototype)實現面向對象。JS建立對象是用原型,實現繼承也是用原型。函數

建立對象:this

var Student = {name: 'abc', height: 1.7}; 
var xiaoming = {name: 'xiaoming'};
xiaoming._proto_ = Student;

clipboard.png

建立對象

JS對每一個建立的對象都會設置一個原型,指向它的原型對象。
當使用obj.***訪問一個對象的屬性時,JS如今當前對象上查找該屬性;若是沒找到,就到其原型對象上找;若是還沒找到,就一直上溯到Object.prototype這個原型對象;最後,若是還沒找到,就返回undefined。這個過程能夠表示爲一個原型鏈spa

// 構造函數對象
function Student(name) {
    this.name = name;  //這裏設置了每一個對象的屬性
}
// 原型對象
Student.prototype.hello = function() {
    alert('Hello, ' + this.name);  //這裏設置了全部對象共享的hello函數,經過繼承得到
}
// 實例對象
var xiaoming = new Student('小明');
var xiaohong = new Student('小紅');

原型鏈以下(圖中紅色箭頭是原型鏈):prototype

xiaoming \
xiaohong -- Student.prototype ----> Object.prototype ----> nullcode

clipboard.png


補充:
見犀牛書對象

原型繼承

Java中,繼承的本質是:擴展一個已有的Class,生成一個新的Subclass。因爲Java嚴格區分實例,繼承其實是類型的擴展blog

而JS沒法直接擴展一個Class,由於不存在Class這種類型,JS採用的是原型繼承繼承

考慮基於Student擴展出PrimaryStudent,原型鏈必須修改成這樣:ip

new PrimaryStudent() ----> PrimaryStudent.prototype ----> Student.prototype ----> Object.prototype ----> null

實現方法:

// PrimaryStudent的構造函數
function PrimaryStudent(props) {
    Student.call(this, props);
    this.grade = props.grade || 1;
}

// 引入中間對象:空函數F
function F() {}
F.prototype = Student.prototype;

// 修改兩個屬性,以實現上述原型鏈
PrimaryStudent.prototype = new F();
PrimaryStudent.prototype.constructor = PrimaryStudent;

// 在PrimaryStudent的原型對象上定義方法
PrimaryStudent.prototype.getGrade = function() {
    return this.grade;
}

// 建立子類對象
var xiaoming = new PrimaryStudent({name: '小明', grade: 60});

// 驗證原型
xiaoming.__proto__ === PrimaryStudent.prototype;     //true
xiaoming.__proto__.__proto__ === Student.prototype;  //true

原型鏈圖示:

clipboard.png

相關文章
相關標籤/搜索