Javascript類和繼承

Javascript中的‘類’

Javascript中并沒有嚴格意義上的類。ES5中通過使用首字母大寫的方法來模擬類。這個首字母大寫的方法也被稱為構(gòu)造函數(shù),其是一個函數(shù)。
構(gòu)造函數(shù)前面用關(guān)鍵字new,則創(chuàng)建一個新的空對象,并用這個新對象調(diào)用這個函數(shù)。

function Person (name) {
  this.name = name;
}  
var per1 = new Person('bob');

其實方法也是對象,方法都是由Function構(gòu)造函數(shù)創(chuàng)建的,F(xiàn)unction由它本身創(chuàng)建。

三個概念

  • 構(gòu)造函數(shù):也是一個函數(shù),一般和關(guān)鍵字new配合使用,你單獨調(diào)用也會不報錯。其本身也是一個對象。
  • 原型對象 : 構(gòu)造函數(shù)的prototype屬性指向的就是原型對象。
  • 實例對象 : new 關(guān)鍵字新創(chuàng)建的對象,new關(guān)鍵字和構(gòu)造函數(shù)一起用,新創(chuàng)建的對象調(diào)用構(gòu)造函數(shù),構(gòu)造函數(shù)里通過this關(guān)鍵字引用實例對象,
    通過this關(guān)鍵字初始化實例對象。

如果構(gòu)造函數(shù)里顯示的返回一個對象,我們聲明的實例對象就是返回的這個

function OBJ(){
  return {name : 1}
};
var other = new OBJ(); 
other.name;  // 1

//other的構(gòu)造函數(shù)為Object , 如果返回的是一個別的構(gòu)造函數(shù)創(chuàng)建的實例對象,other就是指向這個實例對象

一個例子

function Person(name){
  this.name = name
}
var per = new Person("someone");

在這個例子中,Person是構(gòu)造函數(shù),是一個函數(shù)對象,是對象就會有構(gòu)造函數(shù)(Object.prototype對象除外,它是唯一沒有原型和構(gòu)造函數(shù)的對象)
Object.prototype instanceof Object // false 結(jié)果很有趣
函數(shù)對象的構(gòu)造函數(shù)都是Function , Object也是函數(shù)對象,所以 Object的構(gòu)造函數(shù)也是Function.

  • 對象的constructor屬性指向其對應的構(gòu)造函數(shù)
    Person.constructor // ? Function() { [native code] }
    Object.constructor // ? Function() { [native code] }
    Function也是構(gòu)造函數(shù)對象,所以 Function instanceof Function 為true 同時 Function instanceof Object 也為true 而Object instanceof Function也為true 結(jié)果很有趣。
  • 實例對象的proto屬性是瀏覽器實現(xiàn)的一個指向該對象原型對象的屬性。
    Function.____proto____ === Function.prototype
    Function的____proto____指向創(chuàng)建Function的函數(shù)的prototype,F(xiàn)unction由它自己創(chuàng)建。
    Objecet.prototype.___proto____ === null

上面的例子,解釋器會為Person創(chuàng)建一個初始的prototype,這個原型對象中有個constructor屬性指向構(gòu)造函數(shù),在我們給Person指定自定義的對象時,自定義的對象是沒有自己的constructor屬性的(會繼承),除非我們手動添加

實現(xiàn)繼承

  • 給實例對象的原型對象即構(gòu)造函數(shù)的prototype添加方法,或?qū)傩?一般不建議添加屬性),所有的實例對象都會繼承這些方法和屬性,而且這些方法和屬性在實例對象中都是可訪問的。給構(gòu)造函數(shù)添加方法和屬性能模擬實現(xiàn)類方法和類字段

  • 當通過構(gòu)造函數(shù)創(chuàng)建對象時,對象所有的屬性值將會被復制給新的對象。但由于prototype是一個引用類型的變量,存儲的是對象的地址,因此prototype中的所有屬性值將會被該函數(shù)創(chuàng)建的所有對象共享,若一個對象修改了prototype中的某個屬性,那所有對象prototype屬性都會發(fā)生修改。
    因此,prototype屬性適合存儲不變的屬性,如函數(shù);構(gòu)造函數(shù)的普通屬性適合存儲基本類型的屬性;而對象無論存儲在哪里效果都一樣。

  • 此外,將函數(shù)存儲在prototype中可以達到節(jié)約內(nèi)存的功效,不論創(chuàng)建多少對象,該原型對象的函數(shù)在內(nèi)存中只有一份。

  • 在實例對象中通過obj.繼承來的方法/屬性 = somevalue 是無法修改原型對象的方法或?qū)傩缘模驗樵谡{(diào)用對象中的屬性或者方法時,首先會在當前對象中查找是否有該屬性,若無則依次在該對象的原型鏈中找,如果到最后還找不到則返回undefined。obj.繼承來的方法/屬性 = somevalue 會給當前對象創(chuàng)建一個和繼承來的屬性同名的屬性,并且在當前對象中調(diào)用會覆蓋掉繼承來的屬性。

function Student(id){
this.id = id
}

根據(jù)現(xiàn)實邏輯,Student是Person的一類
所以Student的實例應該有Person的特征
繼承是通過prototype表現(xiàn)的,所有類的實例對象都會繼承類(構(gòu)造函數(shù))protptype的屬性和方法。prototype一定是個對象
Student.prototype = inhert(Person.prototype) || new Person();
Student.prototype.constructor = Student //這一句是指定Student實例的構(gòu)造函數(shù)的,如果不指定,不會默認生成,而是使用繼承來的(這里就是Person)

function inherit(obj){
    if(obj == null || (typeof obj !== "object" && typeof obj !== "function")){
        throw TypeError();
    }
    if(Object.create) return Object.create(obj);   //新建一個對象,對象構(gòu)造函數(shù)的prototype為obj
    var f = function(){};
    f.prototype = obj;
    return new f();
}

關(guān)于實例對象的constructor

  • ① var obj = {}; || var obj = new Object();
    obj的構(gòu)造函數(shù)是Object , obj.constructor: Object
    obj的constructor是繼承Object.prototype的,obj.hasOwnProperty(constructor) //false

  • ② function Person(){
    }
    var obj2 =new Person();
    obj2.constructor : Person
    obj的constructor是繼承Person.prototype的。
    Person.prototype : {constructor : Person} //解釋器創(chuàng)建
    解釋器會為Person創(chuàng)建一個初始的prototype,這個原型對象中有個constructor屬性指向構(gòu)造函數(shù),在我們給Person的prototype指定自定義的對象時,自定義的對象會有一個繼承自它的原型對象的constructor屬性,如果要Person的實例對象的constructor正確的指向它的構(gòu)造函數(shù),需要我們手動添加Person.prototype.constructor = Person。
    例如:如果Person.prototype = {name : 'otherobj'};
    var otherobj = new Person(); otherobj.constructor : Object

  • ③ var obj3 = Object.create(obj2) // 創(chuàng)建一個對象,obj3的原型對象為obj2
    obj3.constructor //Person
    obj3.constructor.prototype // obj2
    obj3.constructor.prototype.constructor.prototype //{constructor : Person}
    obj3.constructor.prototype.constructor.prototype.constructor.prototype //Object.prototype

  • ④function Student(){
    }
    Student.prototype = new Person();
    var obj4 =new Student();
    obj4.constructor //Person
    Student.prototype.constructor = Studnet;//手動設(shè)置

//下面兩種錯誤的繼承
Student.prototype = Person.prototype //Student和Person一樣了
Student.prototype = Person //Person這個函數(shù)對象被當作prototype了

var otherCon = Person;
obj4 instanceof otherCon //true instanceof是檢測對象的繼承關(guān)系而不是構(gòu)造函數(shù)
函數(shù)有個name屬性,可以用來看構(gòu)造函數(shù)的name

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,401評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,011評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,263評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,543評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,323評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,874評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,968評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,095評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,605評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,551評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,720評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,242評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 43,961評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,358評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,612評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,330評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,690評論 2 370

推薦閱讀更多精彩內(nèi)容