ECMAScript5中的物件,原型,原型鏈,原型的幾種繼承模式【一】

豫中呼保義發表於2017-09-14

JS的物件和原型;

    天天在講物件,寫了一年的JS程式碼了,在實際的業務開發中(大廠的當我沒說),不使用框架,物件和原型繼承用到的還是非常多的,例如某一個方法在多個物件例項中都會用到,那麼這個時候我們寫原生的JS,封裝方法,實現子類繼承是非常有必要的,如果你不這麼幹,那麼可以收拾收拾桌上的東西,回家了!

    從哪兒開始說呢?我想了一會兒,決定從物件開始說;

    什麼是物件?

    《JavaScript高階程式設計》是這麼說的:物件是若干個(無序的)屬性的集合,屬性是可以包含基本型別資料和(引用型別資料)複合型別資料的識別符號;

    什麼是屬性?

    上面那句話已經說了,看程式碼你就能深刻認識屬性;  

1 name:'振振';     我沒有在外層給他一個掛載的物件,但是一個屬性拿出來就是這個樣子,就是key:value,左邊是鍵名,右邊是值,通過JS的點表示法,可以從物件上訪問到這個鍵名叫做name的屬性,他返回一個字串,就是你寫的這個字串字面量;對,沒錯,這就是屬性,很簡單,你也可以理解成是變數,他儲存了一個字串‘振振’的字元,在變數name中;都沒有問題,只要你能理解他,他就是對的;

    【屬性裡能儲存那些東西?】

    可以儲存:基本資料,和物件(陣列、函式本質上都是物件);

    基本資料是啥?

    JS中一共有幾種基本資料型別?你問我?

    引用型別是啥?

    去看我這篇部落格,你就知道啥是引用型別:http://www.cnblogs.com/wukong-js/articles/7424465.html

    【屬性的分類】

    對,沒錯,屬性有分類,這個分類上面說的是屬性可以儲存的資料型別,這裡說的是屬性的分類,不是一個東西,要分清,不要弄混了;

    有兩個:1.資料屬性 2.訪問器屬性

    【屬性的特性】

    屬性的特性是JS這門語言比較特別的地方,特別在哪兒呢?JS可以讓你精確的控制物件的屬性是否可讀、可寫、可列舉、可配置;{牢記這四點屬性的特性;}

    資料屬性的特性:

      直接上程式碼:

      

1 2 3 4 5 6 7 8 9 10 var obj = { name:'振振' };

obj.defineProperty(obj,'name',function(){ configurable:true/false, enumerable:true/false, writable:true/false, value:'振振的副本' });     這段程式碼很簡單,啥意思呢?

    先說四個特性的意思:可讀就是能不能通過點表示法來獲得這個屬性的值,可寫就是能不能在定義以後修改這個屬性的值,可列舉就是能不能被迴圈遍歷出來,可配置就是屬性的特性定義以後還能不能第二次配置這些可讀可寫可列舉啥的;

    上面程式碼我宣告瞭一個物件叫做obj,然後給了這個物件一個屬性,叫做name,它的值是一個字串;

    如果你想修改物件的屬性的特性需要使用JS給物件內建的一個方法叫做defineProperty()函式,他是Object上的一個方法,就像toString一樣,原生自帶的,所有物件都有這個方法,所以,呼叫的時候直接使用點表示法,呼叫即可;(解釋一下這個點表示法是啥意思:你可以用語文中“的”這個字來代替點,例如obj物件-的-defineProperty方法,就是這麼個意思;);

    【defineProperty方法引數】

    這個方法接受三個引數,第一個引數是,你要修改的--[物件的屬性]--的特性--的物件,(怕你們不會斷句,我幫你斷好了),

               第二個引數是,你要修改的屬性名;

             第三個引數是,一個回撥函式;

     具體設定項的意思:

      configurable:是否可配置;

      enumerable:是否可讀;

      wriable:是否可寫;

      value:屬性的值;

     好了,資料屬性的特性就講完了,這就是用法;之於相容性,IE8及以下有問題,什麼問題我就不說了,如果你們公司還相容IE9及以下的話,離職吧,你別幹了;

    

    訪問器屬性的特性:

      還是先看程式碼:

      

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 var obj = { _age:20, get:function(){ return this._age; }, set:function(value){ this._age = value; } } obj.age;//20; obj.age = 30; obj.age;//30; obj._age;//30;

//或者你可以使用defineProperty()函式來設定訪問器屬性的特性   訪問器屬性一樣是有四個特性:可讀,可寫,可列舉,可配置;

  這個比資料屬性的特性的可讀可寫藥靈活一些,因為我們可以通過get訪問器來精確控制別人訪問這個屬性的時候,我給你什麼值;之於這個 _age是什麼意思,一般加個下劃線的意思是,告訴別人我這是私有屬性,你不要直接訪問,或者是你可以直接將所有的私有屬性設定為不可列舉,這樣就更像是私有屬性;

  【在set和get訪問器這裡有一個知識點比較重要,但是我想到了,突然提筆忘字,忘了,唉,等我想起來在補上吧!】

  【一般只有在設計框架或者是JS類庫的時候才會用到這些知識,平時開發,寫業務,是用不到這些東西的,這個暫時知道一下,或者你可以去讀一讀《你不知道的JavaScript》然後嘗試著設計並實現一個MVC的框架】

  

   【建立物件】

   講了好一會兒物件的屬性,讓我們一起建立一個物件吧;Object;

   建立物件的幾種方式:

  

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 /物件直接量,這種方式是最簡單直觀的,比較常用的/ var obj = { name:'振振' }

/使用new操作符合Object()函式建立物件/ /Object物件是JS中最大的最頂層的那個物件,換句話說,JS中任何一個物件都是由建構函式的方式建立的物件/ var obj = new Object(); /new操作符後面你可以跟任何的函式,建構函式就是普通的函式/

/建構函式建立物件,這種方式用的也非常多,在模擬其他語言的類的繼承的時候,都會選用建構函式加原型的混合模式來建立物件/

function Person(name,age){ this.name = name; this.age = age; this.getName = function(){ return this.name; } } var obj = new Person('振振',20);

/實際上,上面的物件直接量是這樣的:var obj = new Object();/

/還有一種是工廠模式,其實這種我不想說的,因為我覺得不會有人再用這個方式建立物件了/ function createObj(name,age){ var obj = {}; obj.name = name; obj.age = age; obj.getName = function(){ return this.name; } } var ren = createObj('振振',20); 上面說了那麼多,其實最常用的就是物件直接量和建構函式,這兩種方式建立物件;

new了一個物件之後,通過這個物件名然後點表示法跟一個屬性名是啥意思?

意思是,如果這個物件上有這個屬性,則修改屬性,前提是屬性可寫的,如果沒有,則在這個物件上建立一個你點上的這個屬性,就是:obj.name,在obj這個物件上建立了一個name屬性,如果有name屬性就修改name屬性;

【函式中的this】

this是什麼?它充當了指標的作用,它始終指向當前物件,它代表著當前物件,指向所處環境的上一級,如果上一級沒有,就是執行宿主物件,就是Global物件,雖然我們無法訪問到Global物件,但是在宿主環境中,也就是客戶端中的宿主環境中的Glogal物件就是window物件,那麼this就指向window;

一句總結的比較經典的解釋this指向誰:誰呼叫的就指向誰;

看個程式碼,來理解這個誰呼叫就是誰!

1 2 3 4 5 6 7 var o = { name:'haha', getName:function(){ return this.name; } } console.log(o.getName());//haha   我建立了一個物件o,然後給這個物件新增了兩個屬性,一個屬性是基本型別資料,還有一個是引用型別資料,換成人話就是,一個屬性存了一個字串,另一個屬性存的是一個地址,是一個指向堆中儲存函式方法的儲存空間,(如果你不明白,去看我的《ES5中的值傳遞/引用傳遞》這篇部落格;)這個函式執行一個操作,它將給我們返回一個當前物件的name屬性的值;

這個時候是誰呼叫的它,是getName函式嗎?不是,是o物件呼叫了getName方法,而這個方法中的this就是o物件,如果這條return語句這麼寫你就明白了:return o.name;

返回o物件的name屬性;

/天晚了,先說到這裡,明天再說原型/

相關文章