前端——面向對象編程

原型鏈:

JavaScript的面向對象編程和大多數其他語言如Java、C#的面向對象編程都不太一樣。如果你熟悉Java或C#,很好,你一定明白麪向對象的兩個基本概念:

  1. 類:類是對象的類型模板,例如,定義Student類來表示學生,類本身是一種類型,Student表示學生類型,但不表示任何具體的某個學生;

  2. 實例:實例是根據類創建的對象,例如,根據Student類可以創建出xiaomingxiaohongxiaojun等多個實例,每個實例表示一個具體的學生,他們全都屬於Student類型。

所以,類和實例是大多數面向對象編程語言的基本概念。

不過,在JavaScript中,這個概念需要改一改。JavaScript不區分類和實例的概念,而是通過原型(prototype)來實現面向對象編程。

JavaScript的原型鏈和Java的Class區別就在,它沒有“Class”的概念,所有對象都是實例,所謂繼承關係不過是把一個對象的原型指向另一個對象而已。

// 原型對象:
var Student = {
    name: 'Robot',
    height: 1.2,
    run: function () {
        console.log(this.name + ' is running...');
    }
};

function createStudent(name) {
    // 基於Student原型創建一個新對象:
    var s = Object.create(Student);
    // 初始化新對象:
    s.name = name;
    return s;
}

var xiaoming = createStudent('小明');
xiaoming.run(); // 小明 is running...
xiaoming.__proto__ === Student; // true

JavaScript對每個創建的對象都會設置一個原型,指向它的原型對象。

當我們用obj.xxx訪問一個對象的屬性時,JavaScript引擎先在當前對象上查找該屬性,如果沒有找到,就到其原型對象上找,如果還沒有找到,就一直上溯到Object.prototype對象,最後,如果還沒有找到,就只能返回undefined

區別構造函數和普通函數:

構造函數首字母最好大寫;在創建調用的使用需要用new關鍵字調用

普通函數首字母小寫,在創建調用的時候不需要用new關鍵字調用

function Student(props) {
    this.name = props.name || '匿名'; // 默認值爲'匿名'
    this.grade = props.grade || 1; // 默認值爲1
}

Student.prototype.hello = function () {
    alert('Hello, ' + this.name + '!');
};

function createStudent(props) {
    return new Student(props || {})
}

這個createStudent()函數有幾個巨大的優點:一是不需要new來調用,二是參數非常靈活,可以不傳,也可以這麼傳 

var xiaoming = createStudent({
    name: '小明'
});

xiaoming.grade; // 1

對象之間是可以繼承的,在EC6中新增加了class關鍵字,類似於java中的繼承,但是要用super(name)來調用父類的構造函數,否則父類屬性無法正常使用

class PrimaryStudent extends Student {
    constructor(name, grade) {
        super(name); // 記得用super調用父類的構造方法!
        this.grade = grade;
    }

    myGrade() {
        alert('I am at grade ' + this.grade);
    }
}

在EC6之前可以通過一個空的構造函數做中介來實現繼承關係

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章