面向對象的程序設計

你們好,我是蘇日儷格,本文是面向對象的第二部分,純屬我的理解,有哪裏不對的地方請在評論區指出,你們一塊兒學習共同進步。前端

建立對象

在面試中,常常會被問到建立對象都有哪些方式,在建立單個對象的時候一般就用對象字面量,多個對象就用工廠模式、構造函數、原型模式和構造函數原型的混合模式
下面來逐個介紹一下:面試

  • 對象字面量

栗子以下:函數

let Person = {
    name: '蘇日儷格',
    age: 24,
    job: '前端開發'
}
console.log(Person) // {name: "蘇日儷格", age: 24, job: "前端開發"}

優勢:通俗易懂,人人都會的一種簡單的方法
缺點:只適用於建立單個對象,用同一個接口建立多個對象的話,就會有不少的冗餘代碼,爲了解決這個缺點,咱們使用工廠模式學習

  • 工廠模式

栗子以下:測試

function createPerson(name, age, job){
    let obj = new Object();
    obj.name = name;
    obj.age = age;
    obj.job = job;
    obj.show = function(){
        console.log(`姓名:${obj.name}, 年齡:${obj.age}, 工做:${obj.job}`);
    }
    return obj;
}
let person1 = createPerson('蘇日儷格', 24, '前端開發');
person1.show(); // 姓名:蘇日儷格, 年齡:24, 工做:前端開發
let person2 = createPerson('趙雲', 27, '救阿斗');
person2.show(); // 姓名:趙雲, 年齡:27, 工做:救阿斗

優勢:封裝了一個函數解決了代碼冗餘的問題
缺點:沒法明確建立的對象的類型,爲了解決這個缺點,咱們使用構造函數this

  • 構造函數

栗子以下:prototype

function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.show = function(){
        console.log(`姓名:${this.name}, 年齡:${this.age}, 工做:${this.job}`);
    }
}
let person1 = new Person('蘇日儷格', 24, '前端開發');
person1.show(); // 姓名:蘇日儷格, 年齡:24, 工做:前端開發
let person2 = new Person('趙雲', 27, '救阿斗');
person2.show(); // 姓名:趙雲, 年齡:27, 工做:救阿斗

和工廠模式的不一樣之處:code

  1. 沒有顯式的建立對象(new Object())
  2. 沒有return
  3. 直接將屬性和方法賦給了this對象
  4. Person是一個構造函數,首字母大寫(這裏注意,因爲構造函數和普通函數的區別在於有無返回值,並非大小寫,小寫也能夠,可是爲了語義化也算是行規,必須大寫)

優勢:因爲兩個實例共享了show這個全局的方法,就解決了兩個函數作一件事的問題
缺點:若是定義了多個全局的函數,那麼這個自定義的引用類型就絲毫滅有封裝性可言了,並且每一個方法都要在每一個實例上從新建立一遍,爲了解決這個缺點,咱們使用原型模式對象

  • 原型模式

栗子以下:blog

function Person(){}
Person.prototype.name = '蘇日儷格';
Person.prototype.age = 24;
Person.prototype.job = '前端開發';
Person.prototype.show = function(){
    console.log(`姓名:${this.name}, 年齡:${this.age}, 工做:${this.job}`);
}
let person1 = new Person();
person1.show(); // 姓名:蘇日儷格, 年齡:24, 工做:前端開發
let person2 = new Person();
person2.show(); // 姓名:蘇日儷格, 年齡:24, 工做:前端開發
person2.name = '趙雲';
person2.age = 27;
person2.job = '救阿斗';
person2.show(); // 姓名:趙雲, 年齡:27, 工做:救阿斗

優勢:可讓全部對象的實例共享它所包含的屬性和方法,不用再從實例中從新定義信息,直接將信息放在原型對象中
缺點:顯而易見,全部實例都是共享的屬性,可是實例通常會有本身單獨的屬性的,這種方法通常不用,那麼最後一種就是結合了前面全部的缺點的一種方式,也是最讓碼農們認同的

這個時候有些人就想了,重複寫那麼多代碼,咱們能夠簡寫成這樣的啊:

function Person(){}
Person.prototype = {
    name: '蘇日儷格',
    age: 24,
    job: '前端開發',
    show: function(){
        console.log(`姓名:${this.name}, 年齡:${this.age}, 工做:${this.job}`);
    }
}
let person1 = new Person();
person1.show(); // 姓名:蘇日儷格, 年齡:24, 工做:前端開發
let person2 = new Person();
person2.show(); // 姓名:蘇日儷格, 年齡:24, 工做:前端開發
person2.name = '趙雲';
person2.age = 27;
person2.job = '救阿斗';
person2.show(); // 姓名:趙雲, 年齡:27, 工做:救阿斗

上面折中寫法確實清晰了許多,可是這個是在原型模式的狀況下,把構造函數的原型等於了以對象字面量的形式建立的對象,這個時候constructor屬性就再也不指向Person了,爲了證明這一點來看一個小東西instanceof

instanceof 運算符用來測試一個對象在其原型鏈中是否存在一個構造函數的 prototype 屬性。

這句話是什麼意思呢?
來看一個語法:object instanceof constructor
就是用instanceof來檢測一個構造函數的prototype屬性所指向的對象是否存在另一個要檢測對象的原型鏈上
字面理解: constructor.prototype 是否存在於object 的原型鏈上
在上面加上這四行代碼:

console.log(person1 instanceof Person)  // true
console.log(person1 instanceof Object)  // true
console.log(person1.constructor == Person)  // false
console.log(person1.constructor == Object)  // true

很明顯,咱們要的效果出來了,實例的構造函數已經由Person指向了Object,這個時候須要在代碼里加上constructor的指向

Person.prototype = {
    constructor: Person,
    name: '蘇日儷格',
    age: 24,
    job: '前端開發',
    show: function(){
        console.log(`姓名:${this.name}, 年齡:${this.age}, 工做:${this.job}`);
    }
}
  • 構造函數原型的混合模式

栗子以下:

function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
}
Person.prototype = {
    constructor: Person,
    show: function(){
        console.log(`姓名:${this.name}, 年齡:${this.age}, 工做:${this.job}`);
    }
};
let person1 = new Person('蘇日儷格', 24, '前端開發');
person1.show();
let person2 = new Person('趙雲', 27, '救阿斗');
person2.show();

console.log(person1.name == person2.name)   // false
console.log(person1.show == person2.show)   // true

作了個實驗,看看兩個實例究竟是怎樣的,共享的方法獲得了驗證,二者的屬性並非共享的,由於在建立實例的同時,系統開闢了單獨的內存給它,每一個實例也都會給本身的屬性建立一個副本,因此他們以前是互不影響的

優勢:能夠經過構造函數模式來定義實例所須要的屬性,用原型來定義實例共享的屬性和方法(謹記:自己自帶的屬性的權重始終高於原型定義的屬性),分工明確

對象建立好了,關鍵的地方來了,在對象繼承以前先要搞明白__proto__和prototype的關係,這個懂了,就能夠玩原型鏈繼承了^^
本文的全部內容均是一字一句敲上去的,但願你們閱讀完本文能夠有所收穫,由於能力有限,掌握的知識也是不夠全面,歡迎你們提出來一塊兒分享!謝謝O(∩
∩)O~

個人簡書:https://www.jianshu.com/u/72f239ec5d03
等一下( •́ .̫ •̀ ),我還有最後一句話:
我愛你,
爲了尋找你 ,
我搬進鳥的眼睛,
常常盯着路過的風 ,
也忘了聽獵人的槍聲 ,
再見...

相關文章
相關標籤/搜索