JavaScript面向對象 - 建立對象(上)

面向對象是JS的重點與難點,但也是走向「掌握JS」的必經之路,有不少的文章或書籍中都對其進行了詳細的描述,本沒有必要再寫這些,可是對於學習來講,講給別人聽對本身來講是一種更好的受益方式。我想經過簡潔的語言來描述建立對象的方法以及這種方法的優缺點。javascript

本系列內容:java

  1. 基本建立模式segmentfault

  2. 對象字面量建立對象函數

  3. 工廠模式學習

  4. 構造函數模式測試

更新時間this

  1. 2015年12月6日:建立code

  2. 2017年7月8日:精簡內容,修正錯誤對象


1、建立對象

建立對象的方法有許多,各有利弊。知其然,作到會用;知其因此然,作到爲何用這種方法。才能是真正的掌握。ip

1.1 基本建立模式

var person = new Object();
person.name = "張三";
person.job = "學生";
person.viewName = function(){
    console.log(this.name);
}

這是一種最基礎的建立對象的方法,使用新建Object的方法建立對象,而且爲其添加屬性和方法。

但這種方式有個很差的地方是重複使用了多個person變量,並且沒有任何的封裝性可言,因而就出現了更受開發人員喜好的對象字面量形式。

1.2 對象字面量建立對象

var person = {
    name: "張三",
    job: "學生",
    viewName: function(){
        console.log(this.name);
    }
}

這種方式的好處顯而易見,就是解決了以前的缺點。

但在實際需求中,須要建立一批相似的對象就有些力不從心了。好比一個小組有六個成員,我要基於每一個組員進行對象實例化,那麼我要寫6遍以上的代碼,而且爲其命名爲person1~person6。若是能夠像流水線通常建立對象就行了:給其提供原料(名字和職務),讓其自動建立出組員,使用函數剛好能作到。

1.3 工廠模式

var person = function(name, job){
    var o = new Object();
    o.name = name;
    o.job = job;
    o.viewName = function(){
        console.log(this.name);
    }
    return o;
};
var person1 = person("張三","學生");
var person2 = person("李四","學生");

工廠模式利用"建立對象函數"造成流水線的模式,使其流程化,將建立的過程都封裝到函數中,對外只暴露每一個對象的特性(經過參數的形式傳入)。

具體的實現流程是:在函數內建立了一個對象,將傳入的參數做爲對象的屬性,在最後將其返回。調用函數,函數就會返回擁有特定屬性的對象。

工廠模式流程化了建立對象的方法,使其建立對象變得很是簡便,但其中出了一個問題,既然person1和person2都使用person函數建立,那麼,有什麼方法能夠證實person1和person2"師出同門"呢?或者用JS的話說是怎樣解決對象識別問題,答案是工廠模式不能證實。因而又出現了構造函數模式,用此模式能夠肯定person1和person2的關係。

1.4 構造函數模式

var Person = function(name, job){
    this.name = name;
    this.job = job;
    this.viewName = function(){
        console.log(this.name);
    }
}
var person1 = new Person("張三","學生");
var person2 = new Person("李四","學生");

與以前工廠模式的方法對比:

  • Person變量名首字母大寫了

  • 在函數內沒有顯式的建立及返回對象而使用了this

  • 建立時使用了new關鍵字。

Person變量首字母大寫是爲了區別普通函數,除此以外,別無它用。既然Person的首字母大寫只是爲了讓本身一眼辨別出他是構造函數,在功能上是相同的。那麼寫成person固然能夠,只是這樣不推薦(沒法區分普通函數與構造函數)。

使用new操做符必須經歷四個步驟

  1. 建立一個新的對象

  2. 將構造函數的做用域賦值給新對象

  3. 執行構造函數的代碼:爲其添加屬性和方法

  4. 返回新的對象

使用new操做符建立的對象都有一個constructor屬性,該屬性指向構造函數。

person1.constructor == Person; // true
person1.constructor === person2.constructor;// true
console.log(person1.constructor);// 返回構造函數
//function (name, job){
//    this.name = name;
//    this.job = job;
//    this.viewName = function(){
//        console.log(this.name);
//    }
//}

在測試的時候發現一個問題:不使用new關鍵字建立Object對象爲何constructor有值?


共享方法

再回到原來的需求,小組有兩我的,我要建立兩個對象,對象的名字和職位可能不同,可是打印每一個人的名字這個方法是同樣的。

對於以上幾種模式建立的對象。

person1.viewName === person2.viewName;// false

我每次建立一個對象,都建立一次viewName,可是每次都不相等(person1.viewName == person2.viewName返回false)。且若是有一天咱們想把viewName方法改爲return返回name值,我要每一個對象都改嗎?咱們只要把這個方法作成對象公用的就行了,咱們能夠這樣:

var Person = function(name, job){
    this.name = name;
    this.job = job;
    this.viewName = viewName;
}
function viewName(){
    console.log(this.name);
}
var person1 = new Person("張三","學生");
var person2 = new Person("李四","學生");

可是這又出現了一個問題,沒有封裝性可言啊,viewName明明是Person的私有方法,可是放在外面,變成了誰均可以調用,原型函數模式解決了這個問題。

相關文章
相關標籤/搜索