js建立對象的最佳方式

來源:互聯網
上載者:User

標籤:nes   函數指標   簡單   ons   注釋   全域   對象   找不到   for   

1.對象的定義

ECMAScript中,對象是一個無序屬性集,這裡的“屬性”可以是基本值、對象或者函數

2.資料屬性與訪問器屬性
  • 資料屬性即有值的屬性,可以設定屬性唯讀、不可刪除、不可枚舉等等

  • 訪問器屬性是用來設定getter和setter的,在屬性名稱前加上”_”(底線)表示該屬性只能通過訪問器訪問(私人屬性),但並不是說添個底線就把屬性變成私人的了,這隻是習慣約定的一種命名方式而已。訪問器屬性沒什麼用,原因如下:

    var book={  _year:2004,  edition:1}Object.defineProperty(book,"year",{       get:function(){          return this._year;       },       set:function(newValue){          if(newValue>2004){            this._year=newValue;            this.edition+=newValue-2004;          }       }});book.year=2005;alert(book.edition);/*for(var attr in book){  showLine(attr + ‘ = ‘ + book[attr]);}*/

    高程中使用了上面的範例程式碼,原理是book對象的屬性中_year是資料屬性,而year是訪問器屬性,利用gettter和setter可以插入讀寫控制,聽起來不錯。

    但問題是_year和edition都是可枚舉的,也就是說用for...in迴圈可以看到,而訪問器屬性year卻是不可枚舉的。應該公開的訪問器不公開,卻把應該隱藏的私人屬性公開了。

    除此之外,這種定義訪問器的方式並不是全瀏覽器安全色的,[IE9+]才完整支援,當然,也有適用於舊瀏覽器的方式(__defineGetter__()和__defineSetter__()),還是相當麻煩。

    總之,訪問器屬性沒什麼用。

3.建構函式

function Fun(){} var fun = new Fun();其中Fun是建構函式,與普通函數沒有任何聲明方式上的區別,只是調用方式不同(用new操作符調用)而已

建構函式可以用來定義自訂類型,例如:

function MyClass(){  this.attr = value;//成員變數  this.fun = function(){...}//成員函數}

與Java的類聲明有些相似,但也有一些差異,比如this.fun只是一個函數指標,因此完全可以讓它指向可訪問的其它函數(如全域函數),但這樣做會破壞自訂對象的封裝性

4.函數與原型prototype
  1. 聲明函數的同時也建立了一個原型對象,函數名持有該原型對象的引用(fun.prototype)

  2. 可以給原型對象添加屬性,也可以給執行個體對象添加屬性,區別是原型對象的屬性是該類型所有執行個體所共用的,而執行個體對象的屬性是非共用的

  3. 訪問執行個體對象的屬性時,先在該執行個體對象的範圍中尋找,找不到才在原型對象的範圍中尋找,因此執行個體的屬性可以屏蔽原型對象的同名屬性

  4. 原型對象的constructor屬性是一個函數指標,指向函式宣告

  5. 通過原型可以給原生參考型別(Object,Array,String等)添加自訂方法,例如給String添加Chrome不支援但FF支援的startsWith方法:

    var str = ‘this is script‘;//alert(str.startsWith(‘this‘));//Chrome中報錯String.prototype.startsWith = function(strTarget){  return this.indexOf(strTarget) === 0;}alert(str.startsWith(‘this‘));//不報錯了

    注意:不建議給原生對象添加原型屬性,因為這樣可能會意外重寫原生方法,影響其它原生代碼(調用了該方法的原生代碼)

  6. 通過原型可以實現繼承,思路是讓子類的prototype屬性指向父類的執行個體,以增加子類可訪問的屬性,所以用原型鏈串連之後

    子類可訪問的屬性= 子類執行個體屬性 + 子類原型屬性= 子類執行個體屬性 + 父類執行個體屬性 + 父類原型屬性= 子類執行個體屬性 + 父類執行個體屬性 + 父父類執行個體屬性 + 父父類原型屬性= ...

    最終父父...父類原型屬性被替換為Object.prototype指向的原型對象的屬性

    具體實現是SubType.prototype = new SuperType();可稱之為簡單原型鏈方式的繼承

5.建立自訂類型的最佳方式(建構函式模式 + 原型模式)

執行個體屬性用建構函式聲明,共用屬性用原型聲明,具體實現如下:

    function MyObject(){      //執行個體屬性      this.attr = value;      this.arr = [value1, value2...];    }    MyObject.prototype = {      constructor: MyObject,//保證子類持有正確的構造器引用,否則子類執行個體的constructor將指向Object的構造器,因為我們把原型改成匿名對象了      //共用屬性      fun: function(){...}    }
6.實現繼承的最佳方式(寄生組合式繼承)
function object(obj){//返回原型為obj的沒有執行個體屬性的對象  function Fun(){}  Fun.prototype = obj;  return new Fun();}function inheritPrototype(subType, superType){  var prototype = object(superType.prototype);//建立原型鏈,繼承父類原型屬性,用自訂函數object處理是為了避免作為子類原型的父類執行個體具有執行個體屬性,簡單地說,就是為了切掉除多餘的執行個體屬性,可以對比組合繼承理解  prototype.constructor = subType;//保證構造器正確,原型鏈會改變子類持有的構造器引用,建立原型鏈後應該再改回來  subType.prototype = prototype;}function SubType(arg1, arg2...){  SuperType.call(this, arg1, arg2...);//繼承父類執行個體屬性  this.attr = value;//子類執行個體屬性}inheritPrototype(SubType, SuperType);

具體解釋見代碼注釋,這種方式避免了SubType.prototype = new SuperType();簡單原型鏈的缺點:

  • 子類執行個體共用父類執行個體引用屬性的問題(因為原型引用屬性是所有執行個體共用的,建立原型鏈後父類的執行個體屬性就自然地成了子類的原型屬性)。

  • 建立子類執行個體時無法給父類建構函式傳參

7.實現繼承的最常用方式(組合繼承)

把上面的inheritPrototype(SubType, SuperType);語句換成:

SubType.prototype = new SuperType();SubType.prototype.constructor = SubType;

這種方式的缺點是:由於調用了2次父類的構造方法,會存在一份多餘的父類執行個體屬性,具體原因如下:

第一次SuperType.call(this);語句從父類拷貝了一份父類執行個體屬性給子類作為子類的執行個體屬性,第二次SubType.prototype = new SuperType();建立父類執行個體作為子類原型,此時這個父類執行個體就又有了一份執行個體屬性,但這份會被第一次拷貝來的執行個體屬性屏蔽掉,所以多餘。

js建立對象的最佳方式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.