初識JavaScript對象與繼承

      網友投稿 621 2025-03-31

      javaScript中的“對象”可謂是“王”一般的存在。對象是一個“個體”,其中的屬性定義了這個“個體”的信息。


      首先創建一個對象可以使用如下的方法:

      //第一種,直接new出來一個? ????????var?test_one?=?new?Object(); ????????//?然后運用點方法為其增加屬性 ????????test_one.name?=?'hello'; ????????//?第二種為用對象字面量法 ????????//?這種方法好用,但是如果要為其增加屬性,不得使用字面量,因為會重新定義(或者說把新的東西賦值給了對象) ????????var?test_two?=?{name:'hello',age:100}; ????????console.log(test_one.name,test_two.age);

      接下來便是屬性類型,屬性由一些特征值去設置

      (簡單點理解就是你設置了一個屬性,然后要設置這個屬性的一些操作,比如可不可以修改,可不可以顯示出來。。。)

      屬性類型分為數據屬性與訪問器屬性,且都有四個特征值。

      數據屬性的特征值為:Configurable,Enumerable,Writable,Value。

      訪問器屬性的特征值:Configurable,Enumerable,get,set。

      configurable:即設置屬性能否被刪除,或者重新定義,修改屬性。

      writable:設置能否修改屬性的值。

      enumerable:屬性是否可以被for循環返回。

      value:屬性的值。

      想要修改某屬性的特征值可以采用object.difineProtype()函數,其接受三個參數分別為:屬性所在的的對象,屬性,一個描述符對象(描述符對象里存放著以特征值為屬性名的數據)

      看了也不懂,我們直接看例子

      var?test?=?{age:12} ????????//?為test設置一個數據類型的屬性 ????????//?在用object.defineProtype設置一個屬性時,如果不指定,configuratable,enumerable,writable,都默認為false ????????//?注意傳的屬性名字是字符串的 ????????Object.defineProperty(test,'name',{value:'hello',configurable:true,enumerable:false}) ????????test.name?=?'baibai' ????????//?在這里我們沒有設置writable所以用object.defineProtype創建的屬性默認為false ????????console.log(test.name); ????????//?由于enumerable為false,所以name屬性不可以被迭代 ????????for?(var?i?in?test){ ????????????console.log(i); ????????} ????????console.log('-----------分割線---------'); ????????//?重新設置name屬性,設置writable和writable ????????Object.defineProperty(test,'name',{value:'hello',configurable:true,enumerable:true,writable:true}) ????????test.name?=?'baibai' ????????//?發現可以修改了 ????????console.log(test.name); ????????//可以被迭代 ????????for?(var?i?in?test){ ????????????console.log(i); ????????} ????????console.log('---------分割線--------'); ????????//但當configurable設置為false,屬性不可以像上面那樣可以改進行重新定義 ????????//而且也不可以重新設置configurable為ture。 ????????Object.defineProperty(test,'name',{value:'hello',configurable:false,enumerable:false}) ????????//?會報錯 ????????Object.defineProperty(test,'name',{value:'world',configurable:true,enumerable:false})

      訪問器屬性與數據屬性差不多,不同在于get函數與set函數,這里舉個例子:

      //?通過改變對象person在哪一年開始讀書,相應的改變這個人讀了幾年書 ????????var?person?=?{ ????????????inschool_age:2008,?????????//2008年開始讀書 ????????????readbook_age:12????????????//讀了12年了 ????????} ????????Object.defineProperty(person,'inschool_age',{ ????????????get?:function(){ ????????????????return?this.inschool_age ????????????}, ????????????set:function(inschool_age){ ????????????????this.readbook_age?=?2020?-?inschool_age ????????????} ????????}) ????????person.inschool_age?=?2010; ????????console.log(person.readbook_age);

      二、有了對象,我們可以設置一個個體的屬性,達到操作的目的。

      但如果一個一個操作,著實有點麻煩。為此,我們需要找到這些對象之間有的共性。比如學生有學號,我們可以將學生作為一個群體,對于每次構造學生這個對象的時候,都賦予學號這個屬性。相當于通過這個類型可以創造出具有相同屬性,值不同的對象;

      同時學生擁有學號,工人擁有工號,其實本質上差別不大,那可以那學生的模板來用在工人身上,這就是需要將學生的屬性“繼承”到工人身上。

      1、在這里我們先了解一個東西----指針(C語言之靈魂)。

      指針(個人理解):即存放一個變量,也占據內存,但其存放的值,是另外一個變量的地址,指向了那個變量。算了,看圖。

      指針存放了變量的地址,然后指向了變量。相當于定義了一個變量(指針)存放的不是值,而是另一個變量所存放的地址。(個人見解)

      2、構造函數:以下均為個人見解

      第一種

      function?people(name,year){ ????????????var?test?=?{}; ????????????test.name?=?name; ????????????test.year?=?year; ????????????test.sayhello?=?function?(){console.log('hello');} ????????????return?test ????????} ????????var?one?=?people('hello',10); ????????var?two?=?people('one',23) ????????console.log(one.name); ????????//在這里我們發現one不是基于people的實例 ????????console.log(one?instanceof?people);????//false ????????console.log(one.sayhello?==?two.sayhello);??//false ????????console.log(test.name);???????????????//報錯

      個人的猜測:對象可以算一個指針,但又可以存放更多的數據,不只存放地址,(也可以說對象其實是一塊和程序聲明屬于自己的內存區域)。在將people('hello',10)賦給one時,應該傳的是數據即 var one = {name:'helllo',year:10};而不是直接把一個對象給one,而且test對象在函數執行完就不存在了,所以訪問不了。

      function?people(name,year){ ????????????this.name?=?name; ????????????this.year?=?year; ????????} ????????var?one?=?new?people('hello',10); ????????console.log(one.name); ????????console.log(one?instanceof?people);??//true

      個人的猜測:new一下,就會有一個對象,那這個對象指向哪?上面例子new 指向了函數people,然后function的this又回指了new出來的對象實例。(因為函數也是對象)

      前面兩個例子第一個因為無論怎么創建,對象都是基于object創建的,而不是我們自己定義的類型。還有每一次定義下來的方法是一個實例的方法,不是共有的。

      第二個例子解決了自定義類型的問題而已。所以

      原型模式:

      我們創建的每個函數都有一個prototype屬性,這個屬性是一個指針,指向一個對象(原型對象),而這個對象的用途是包含可以由特定類型的所有實例共享的方法和屬性。在默認情況下,所有原型對象都會自動獲得一個constructor屬性,這是一個指向prototype屬性所在函數的指針。如圖(圖片來源:紅寶書):

      function?people(){ ????????} ????????people.prototype.name?='D'; ????????people.prototype.age?=?12; ????????people.prototype.sayhello?=?function(){ ????????????console.log('hello'); ????????} ????????var?person1?=?new?people(); ????????var?person2?=?new?people(); ????????person1.sayhello(); ????????person2.sayhello(); ????????console.log(person1.sayhello?==?person2.sayhello);?//true

      同時,也可以修改對象的已有屬性,或者添加屬性。注意:修改并不是修改,而是為實例添加,從而覆蓋掉原型的同名屬性。如例子:

      function?people(){ ????????} ????????people.prototype.name?='D'; ????????people.prototype.age?=?12; ????????people.prototype.sayhello?=?function(){ ????????????console.log('hello'); ????????} ????????var?person1?=?new?people(); ????????var?person2?=?new?people(); ????????person1.sayhello(); ????????person2.sayhello(); ????????console.log(person1.sayhello?==?person2.sayhello); ????????console.log(person1.name?==?person2.name); ????????console.log(person1.name); ????????//當為對象添加原型已有的屬性,則會覆蓋原型的屬性,而用實例的屬性 ????????person1.name?=?'馬云'; ????????console.log(person1.name); ????????console.log(person1.name?==?person2.name);?//可見更改之后,用的不是原型的屬性name了 ????????//也可以使用hasOwnprotype()檢測屬性是實例的還是原型的。

      原型模式也可以采用字面量的方式賦值簡化,但是需要為constructor設置為其prototype所在函數的函數名。因為字面量方式相當于重寫了原型模式。并沒有默認的帶一個指針constructor。

      function?people(){ ????????} ????????people.prototype?=?{ ????????????construtor:people, ????????????name:'D', ????????}

      以這種方式設置的constructor默認是可枚舉的,而原本的是不可以被枚舉的。也可以使用前面的訪問器屬性重新設置該屬性。這里不舉例了。

      同時字面量方式修改原型對象,也會影響原型對象的動態性(即實例后的對象,如果我為原型對象增加了新的方法,會立馬反應到實列中)。如:

      function?people(){ ????????} ????????people.prototype.name?=?'D'; ????????var?one?=?new?people(); ????????people.prototype.age?=?12; ????????//age屬性在實例化one后面,卻馬上反應到了one實例中。 ????????console.log(one.age); ????????people.prototype?=?{ ????????????name:'d' ????????} ????????var?two?=?new?people(); ????????console.log(two.name,two.age);

      原型對象在基本數據的共享是可以的,但是如果運用引用類型的數據,就不行。因為引用類型值的屬性,是一個指針,指向了數據存放的地址。如果共享了的話,相當于每一個實例的引用類型屬性,所存放的都是同一個地址。如:

      function?students(){ ????????} ????????students.prototype.name?=?['馬云','比爾蓋茨']; ????????var?one?=?new?students(); ????????var?two?=?new?students(); ????????one.name[2]='華為云'; ????????console.log(one.name); ????????//并沒有設置two的屬性,但卻更改了 ????????console.log(two.name);

      前面我們由于不使用構造函數是因為每一次都會為實例添加一個相同的方法或屬性,達不到共用的效果。后面我們說了原型可以實訓共用,但要設置屬于自己的,則只有通過創建相同屬性覆蓋掉原型。所以將兩者都使用,構造函數用于特有的屬性和方法設置,原型模式用于共享。如:

      function?student(name,age){ ????????????this.name?=?name; ????????????this.age?=?age; ????????} ????????student.prototype.sayhello?=?function?(){ ????????????console.log('hello'); ????????} ????????var?one?=?new?student('D',2); ????????var?two?=?new?student('d',3); ????????console.log(two.age?==?one.age);???//由于這個屬性是每個對象特有的,使用false ????????console.log(two.sayhello?==?one.sayhello);??//sayhello在原型對象中,所以為ture ????????one.sayhello(); ????????two.sayhello();

      原型鏈:前面我們說到,為實例添加一個原型對象擁有的屬性,會覆蓋掉原型對象的同名屬性,其實是每一次,都進行一次搜索。即先從實例搜一下,沒有,那去原型對象看看,原型對象也沒有,那就去原型對象的原型對象看看。。。。。從上面那里,我們知道原型鏈就像‘你的祖宗’,如果每一輩有一個傳家寶,那我想要知道這個傳家寶是那一輩留下了的,就要往上找!!!

      繼承:我們知道構造函數都有一個prototype屬性指向了它的原型對象,然后原型對象有一個constructor屬性回指了構造函數,實例有一個[[prototype]]屬性指向了原型對象。這樣實例是不是就擁有了原型對象的所有屬性和方法。那我們將另一個原型對象(2)設置為該原型對象(1)的實例,是不是這個原型對象(2)就有了原型對象(1)的所有屬性和方法。如:

      function?people(){ ????????????this.name?=?'D'; ????????} ????????people.prototype.sayhello=function(){console.log('hello');} ????????function?student(){ ????????} ????????student.prototype?=?new?people(); ????????var?test?=?new?student(); ????????test.sayhello(); ????????console.log(test.name);

      在這個例子中,我們發現student繼承了people的方法,但連在構造函數中的屬性name也繼承了,是為什么?前面我們說到原型鏈,找不到屬性,會向上級找,所以在執行student.prototype時,該原型對象已經被改寫了,里面沒有constructor屬性,所以,他就向他的上級(即被繼承的原型對象)找,找到了people。constructor的屬性,而該屬性指向了構造函數people。

      起初認為這樣子把構造函數繼承下來也挺好的,但是后面問題就是:如何給子類型添加屬性?去改父類型!那父類型也要更改?(其實可以將想加在子類的屬性,在父類設置,傳參的時候,父類就傳自己有的實參,而運用子類的時候,就傳比父類更多的參數,因為多余的形參會是undefined)- --->本人的胡思亂想,哈哈。

      解決的辦法就是將父類的構造函數調到子類的構造函數中使用

      function?student(name,age,year){ ???????????this.name?=?name; ???????????this.age?=?age; ???????????this.year?=?year; ???????} ???????student.prototype.sayhello?=?function(){ ???????????console.log('hello'); ???????} ???????function?teacher(name,age,year,classbook){ ???????????student.call(this,name,age,year)???//運用call方法把父類的構造函數調到teacher中使用 ???????????this.classbook?=?classbook;???????????//為子類添加新的屬性 ???????} ???????teacher.prototype?=?new?student(); ???????teacher.prototype.construtor?=?teacher;???//讓子類的構造函數指向他自己的構造函數 ???????teacher.prototype.response?=?function?(){ ???????????console.log('hello?too!'); ???????} ???????var?student_one?=?new?student('D',24,1); ???????var?teacher_one?=?new?teacher('d',20,2,'huaxue'); ???????student_one.sayhello(); ???????console.log(student_one.name,student_one.age,student_one.year); ???????console.log(teacher_one.name,teacher_one.classbook); ???????teacher_one.response(); ???????teacher_one.sayhello();

      將原型對象更改為另外一條原型鏈的某一結點的原型對象,就好比:這個傳家寶找到了,在你爺爺那一輩傳下來的,那么這個傳家寶是自己做出來的,還是花錢從別人那里買下來(繼承),又或是搶回來的(哈哈哈哈),后來作為傳家寶的。

      個人感覺javaScript的類型,其實只有一種即object,所有的類型都是基于object prototype原型而寫的。比如:

      function?people(){}????????//個人覺得在此步就已經運用了object的原型對象,然后people作為object的一個實例 ????????function?student(){}??????? ????????stuedent.prototype?=?new?people();?????//student從people那里買(搶)傳家寶。

      就吐槽到這了,如此文有錯誤,希望能為我指出,因為很多都是自己的看法。。。。。。。

      初識JavaScript對象與繼承

      JavaScript Prototype

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:項目協同管理,提升團隊效率的關鍵
      下一篇:【華為云Stack】【大架光臨】第8期:“云聯邦”構建連云成片、無縫混合的一朵云
      相關文章
      国产AV无码专区亚洲精品| 亚洲中文字幕无码一区| 亚洲国产精品VA在线看黑人| 亚洲国产av无码精品| 婷婷国产偷v国产偷v亚洲| 亚洲AV日韩AV无码污污网站| 亚洲人成综合网站7777香蕉| 亚洲首页国产精品丝袜| 亚洲人成网男女大片在线播放| 亚洲人成电影青青在线播放| 亚洲免费视频观看| 亚洲日本国产综合高清| 亚洲熟女乱色一区二区三区| 亚洲色大成网站www| 亚洲av综合av一区二区三区| 精品国产亚洲AV麻豆| 亚洲国产精品一区二区第四页 | 亚洲国产人成网站在线电影动漫| 亚洲va中文字幕无码久久不卡 | 亚洲春色在线视频| 亚洲一区二区在线视频| 亚洲视频在线观看地址| 91亚洲性爱在线视频| 中国亚洲呦女专区| 亚洲成AV人片高潮喷水| 亚洲成a人无码av波多野按摩| 亚洲精品网站在线观看不卡无广告 | 亚洲av无码专区在线电影天堂 | heyzo亚洲精品日韩| 不卡一卡二卡三亚洲| 久久亚洲AV无码精品色午夜麻| 亚洲国产成人精品不卡青青草原| 亚洲福利秒拍一区二区| 亚洲AV无码一区二区三区人| 亚洲日本在线电影| 亚洲第一视频在线观看免费| 国产亚洲人成无码网在线观看| 久久亚洲中文字幕精品有坂深雪| 亚洲精品乱码久久久久久下载 | 久久精品国产亚洲夜色AV网站| 337p欧洲亚洲大胆艺术|