前言
????即使不了解Javascript的設(shè)計原理和繼承機(jī)制這些東西的時候,我們依然能很好的使用Javascript去設(shè)計前端頁面及功能。
????這得力于傳統(tǒng)jquery時的前端開發(fā)我們把大部分的業(yè)務(wù)邏輯封裝在后臺,前端代碼的邏輯性大大降低,我們只需要使用一點點j和ava語法類似的知識就能寫出所需的javascript代碼。
????這時候我們不需要考慮繼承,不需要考慮復(fù)雜的封裝,甚至連this關(guān)鍵字我們都用的極少。但在接觸了react,vue這些前端框架之后就有必要詳細(xì)的了解與學(xué)習(xí)Javascript了,Javascript已經(jīng)變成一個獨(dú)立于后端的完整的前端框架的一個基礎(chǔ)。
對象及對象的創(chuàng)建
????Javascript是一種基于對象(object-based)的語言,你遇到的所有東西幾乎都是對象。但是,它又不是一種真正的面向?qū)ο缶幊蹋∣OP)語言,因為它的語法中沒有"子類"和"父類"的概念,也沒有"類"(class)和"實例"(instance)的區(qū)分。我們舉幾個例子,一下的都是對象。
????這些基礎(chǔ)的數(shù)據(jù)類型也是對象但是不在本章的討論訪問之內(nèi)。
這兩行都是等價的,都生成了一個名為fun1的(函數(shù))對象。
????這是我們比較常見的對象方式,用大括號的方式創(chuàng)建對象,采用鍵值對的方式描述對象屬性。
????這個對象的結(jié)果其實和第三個對象是一樣的都是可以用{}來表述的。
????我們可以很清楚的看出這都是對象,完全沒有類的概念,我們最后一個例子里的Object是類么?不,不是的。接下來就要說明一下對象的創(chuàng)建方式。
順便給大家推薦一個裙,它的前面是 537,中間是631,最后就是 707。想要學(xué)習(xí)前端的小伙伴可以加入我們一起學(xué)習(xí),互相幫助。群里每天晚上都有大神免費(fèi)直播上課,如果不是想學(xué)習(xí)的小伙伴就不要加啦。
????對象的創(chuàng)建方式只有一種,那就是
????所以我們很清楚了,Object是一個構(gòu)造函數(shù)(對象)。
????這么設(shè)計的原因是因為當(dāng)初javascript的設(shè)計者并不打算引入"類"(class)的概念,因為一旦有了"類",Javascript就是一種完整的面向?qū)ο缶幊陶Z言了,這好像有點太正式了,而且增加了初學(xué)者的入門難度。不過他在設(shè)計創(chuàng)建對象的方式上卻借鑒了C++和java的語法,引用了new關(guān)鍵字,但是javascript是沒有類的?那么new后面跟著是什么呢?它發(fā)現(xiàn)java與C++對象的創(chuàng)建都必須執(zhí)行構(gòu)造函數(shù)(constructor),于是乎他就做了簡化的設(shè)計,在Javascript語言中,new命令后面跟的不是類,而是構(gòu)造函數(shù)。
????所以以上四種范例其本質(zhì)上都是javascript通過new 構(gòu)造函數(shù)的方式隱式或顯式幫我們創(chuàng)建的。我們先詳細(xì)的了解一下構(gòu)造函數(shù)的創(chuàng)建方式再細(xì)說范例中是如何隱式創(chuàng)建的對象。
構(gòu)造函數(shù) construct
示例:
????7丨console.log(zs); //[object Object] ?
{[functions]: , __proto__: { },age: 23,name:"zhangsan",sex: "man"}
????可以看到我們根據(jù)man構(gòu)造函數(shù)創(chuàng)建了一個對象zs,對象有name,age和sex 屬性。在這里面我們可以清楚的看到構(gòu)造函數(shù)給對象設(shè)置屬性的方式是this關(guān)鍵字,this關(guān)鍵字動態(tài)指向的是創(chuàng)建的對象(關(guān)于this的其它問題會另起一章介紹),this關(guān)鍵字后跟著的屬性或方法就是該對象的屬性或方法。但是如果構(gòu)造方法有返回值,那生成的對象就是構(gòu)造方法的返回值了,所以大家在寫構(gòu)造方法時要特別注意,示例如下:
????看到zs的值變成了{(lán)info:‘error’},所以寫構(gòu)造函數(shù)的時候最好也不要寫返回值。但是我發(fā)另一很奇怪的情況,示例如下
丨:"zhangsan",sex: "man"}
????我們看到如果返回的是基本類型,整型,字符串類型等的那構(gòu)造函數(shù)還是生效了,這另我十分費(fèi)解。不過只要記住在我們寫構(gòu)造函數(shù)時不去寫返回值也就能規(guī)避這種問題。
????構(gòu)造函數(shù)創(chuàng)建的方式也不是完全完美的,比如看下面的示例中的sex屬性,如果通過man構(gòu)造函數(shù)創(chuàng)建出來的對象sex都固定是“man”,那每個對象都要分配內(nèi)存來存儲sex屬性是不是有些浪費(fèi)呢?或者就是有些屬性要給所有對象共用的呢?比如對象的方法,完全不需要隨著對象變化,該如何處理?
????為了解決這個問題,javascript為構(gòu)造函數(shù)(函數(shù)類型對象)提供了prototype屬性。
prototype屬性
????prototype只能用于函數(shù)對象,如果你給其它非函數(shù)對象增加prototype屬性,執(zhí)行器會報出該對象無prototype屬性錯誤。
????我們先來一個示例來看prototype如何使用
????我們看到構(gòu)造函數(shù)通過prototype屬性增加的屬性或方法是給所有對象共享的。我們把那些需要共享的方法和屬性放在prototype屬性里,那些不需要共享的屬性和方法,就放在構(gòu)造函數(shù)里面。
????而實現(xiàn)過程是這樣的,當(dāng)實例對象一旦創(chuàng)建,將自動引用prototype對象的屬性和方法。也就是說,實例對象的屬性和方法,分成兩種,一種是本地的,另一種是引用的。
順便給大家推薦一個裙,它的前面是 537,中間是631,最后就是 707。想要學(xué)習(xí)前端的小伙伴可以加入我們一起學(xué)習(xí),互相幫助。群里每天晚上都有大神免費(fèi)直播上課,如果不是想學(xué)習(xí)的小伙伴就不要加啦。
????我們再看一個示例
????我們看到只有通過prototype屬性修改sex對象才能更新全部對象的sex屬性,而單單修改某個對象的sex屬性是無法全局修改的,對于這個我不知道是如何實現(xiàn)的,有知道的不吝賜教。
????我們再看一個示例
????這個示例只是prototype下屬性的修改方式改為對整個prototype屬性的對象進(jìn)行設(shè)置。這種方式可以么?可以,而且修改成這樣對上一個示例的輸出完全沒有影響。但是個人還是不推薦這種方式,因為prototype屬性還有一個特別的方法constructor。
constructor
????我們先介紹下constructor屬性
constructor屬性是指向構(gòu)造方法的引用,也就是說如下兩行代碼是等價的。
????看起來好像沒什么用,但是我們知道prototype可以把自己的屬性傳遞給對象的。也就是說我們可以通過constructor來比較兩個對象是不是同一個構(gòu)造器的實例,示例如下:
????所以通過man.prototype={…}的方式設(shè)置共享屬性會破壞constructor屬性。雖然好像破壞了在我們的使用中不會產(chǎn)生任何影響,但我們還是要知道有這個屬性的存在及prototype的作用。
????prototype還有一些其他方法,但是通過man.prototype={…}方式是破壞不了,只是因為所有對象的這些方法都是一致的,比如isPrototypeOf,hasOwnProperty方法,提供幾個示例,就不詳述了。
????isPrototypeOf 示例是不是來自該構(gòu)造函數(shù)
????hasOwnProperty 每個實例對象都有該方法,用來判斷某一個屬性到底是本地屬性,還是繼承自prototype對象的屬性
????我們再看一下最開始我們說的那個問題,所有的對象生成本質(zhì)上都是通過構(gòu)造函數(shù)生成的。查看的方法很簡單,我們知道每個對象都有一個constructor方法,我們只要輸出每個對象的constructor方法就能找到他的構(gòu)造函數(shù)。
其它問題
????我們說了構(gòu)造函數(shù),什么樣才能算是構(gòu)造函數(shù)呢?所有的函數(shù)都可以是構(gòu)造函數(shù),所有的函數(shù)也只有函數(shù)可以擁有有prototype屬性。而函數(shù)也是對象,如上面例子的fun1函數(shù),它也是由Function()構(gòu)造函數(shù)生成的,fun1是函數(shù)對象,你可以把fun1當(dāng)對象用,給他設(shè)置屬性,方法都是完全沒問題的,但是fun1.prototype設(shè)置的屬性也只能給new fun1()生成的對象使用,不能混淆了。
????有說javascript的繼承機(jī)制是依靠prototype屬性(原型鏈{prototype chain}模式)來實現(xiàn)的,但是因為通過prototype設(shè)置“父對象”的屬性和方法,只能變成“繼承”共享的屬性和方法,每個對象自己私有的屬性和方法是無法繼承的,還是有一些不一樣的。而且說是共享只能說是統(tǒng)一賦值,我們通過對象去修改prototype提供的屬性并不會影響其他對象的該屬性。說是繼承但是不太一樣。
????在理解javascript的對象及對象的創(chuàng)建時要牢記兩點,一個是javascript內(nèi)(幾乎)所有的都是對象,并且對象都有構(gòu)造函數(shù)和一些默認(rèn)方法。比如我有時忘記這兩件事,寫一些奇怪的范例時就很懵逼,為什么會出現(xiàn)這個結(jié)果。如我常忘記prototype屬性指向的也是對象,對象也就會有constructor,isPrototypeOf 等這些方法。
作者:spongeboblz??
來源:CSDN????????????????????????????????????????