js對象建立方法彙總及對比

js中建立對象的方式有不少,尤爲是基於原型的方式建立對象,是理解基於原型繼承的基礎。所以在這裏彙總一下,並對各類方法的利弊進行總結和對比,不至於之後對這些概念有模糊。javascript

簡單方式建立

var o = new Object();

咱們都知道,實際上在javascript中並無所謂的類的概念。所以在建立對象時不能像面嚮對象語言那樣,經過類A new出來一個a對象。可是javascript有一個特殊的Object。咱們能夠藉助Object來new一個對象。
而後能夠經過以下方式給對象增長屬性或方法:java

o.name="abc";

可是由於沒有類的約束,這種方式建立出來的對象沒法實現對象的重複利用,而且沒有一種固定的約數,操做起來可能會出現這樣或者那樣的意想不到的問題。
有這樣一個例子:json

var a = new Object;  
    var b = new Object;  
    var c = new Object;  
    c[a]=a;  
    c[b]=b;  
    alert(c[a]===a); //輸出什麼

關於這個例子的具體解答詳見 例子出處函數

工廠方法建立

直接看一個例子:優化

function createPerson(){
        var o = new Object();
        o.name = "abc";
        o.age = 20;
        return o;    
    }

這種建立對象的方法是在一個function中new Object(),而且賦予屬性和方法,最後return 帶有這些屬性和方法的對象。this

可是當咱們想經過spa

var p1 = createPerson();
    alert(typeof(p1));//Object 僅能獲得這個結果,實際上沒有太大意義
    alert(p1 instanceof(類名???))//會發現其實並不存在一個Person類

構造函數的方式

function Person(name,age){
        this.name = name;
        this.age = age;
        this.say = function(){
            //
        }
    }
    
    var p1 = new Person('abc',20);

構造函數的方式建立的對象:prototype

  • 函數名即爲類名code

  • 經過this來定義屬性對象

  • 經過new Person()建立對象

  • 而且有以下屬性:

alert(typeof(p1));// Person
    alert(p1 instanceof(Person));// true
  • 可是同時咱們也發現這種方式建立對象的一個弊端。對於類中的say方法,每分配一個對象就會有一個say的內存空間被分配出來。有一個say的拷貝。若是方法特別多的時候,會形成內存空間的極大浪費。能夠經過兩種方式進行優化和改進:

    • 將say聲明爲全局的

      function say(){
          
          }

      而後在類的定義中經過:

      this.say = say;
    • 採用下面提到的基於原型的方式建立對象

讓類中的行爲統一指向全局的say方法。可是若是將全部的方法設爲全局的時候,就能夠被window對象調用,那麼就破壞了對象的封裝性;若是方法不少,會形成代碼中充斥着大量的全局函數。

基於原型建立對象

function Person(){
        
    }
    Person.prototype.name = "abc";
    Person.prototype.age= 20;
    Person.prototype.say= function(){
        alert(this.name+this.age);
    }
    
    
    var p1 = new Person();
    p1.say();//ok
    say();//no 完成了封裝

原型是js中的一個特殊對象。當一個函數建立以後,會隨之產生一個原型對象。該函數中的prototype屬性指向該源性對象;
當經過該函數的構造函數建立一個具體對象時,在這個對象中,就會有一個_prop_屬性指向原型。這些是js中的很重要的一種繼承方式--基於原型的繼承的基礎。這裏再也不贅述。

基於原型建立對象時,若是對象的屬性和方法特別多時,能夠經過以下方式進行定義:

Person.prototype = {
        name:"abc",
        age:20,
        say:function(){
        
        }
    }

稱爲原型重寫。原型重寫以後當咱們再經過 var p1 = new Person()建立一個對象時,p1 的constructor != Person()了。因爲原型重寫了,並且沒有經過prototype指向,從而指向了Object()。
若是constructor比較重要,能夠再json格式的定義中手動制定

constructor:Pserson

關於原型重寫,我畫了個示意圖,比較容易理解:

圖片描述

p1是原型重寫前聲明的對象,p2是原型重寫

Person.prototype.name = "123";

以後的聲明的對象。
能夠看出

  • constructor的指向確實沒有自動變換,除非經過上述手動的方式進行修改。

  • 經過p2.name = "456",設置name時,會在本身的存儲空間中存儲。固然查找name屬性時,也是從本身的內存空間中讀取name值。

相關文章
相關標籤/搜索