摘要:注意這種只能發(fā)生在單參數(shù)構(gòu)造函數(shù)中舉個例子創(chuàng)建一個類,類該類如下,有個單參數(shù)的構(gòu)造函數(shù)。默認構(gòu)造函數(shù)當構(gòu)造函數(shù)不帶參數(shù)時,我們就把這個構(gòu)造函數(shù)叫做默認構(gòu)造函數(shù)。
其實兩個月前我寫過一篇C++基礎文章:關于構(gòu)造函數(shù)的基本用法,文章鏈接傳送門?:c++基礎 面向?qū)ο螅旱谖迤?gòu)造,析構(gòu),拷貝函數(shù)),但是,這里僅僅是基礎中的用法,并沒有涉及太多的講解,打算今天整理以下,我對構(gòu)造函數(shù)的再度理解,分享給大家。
構(gòu)造函數(shù)的作用,存在意義,目的:用來初始化類對象的成員變量的函數(shù)
如何理解呢?其實就是為了封裝性(我的理解),當我們定義一個類對象時候,其實可以在類外直接使用對象.成員變量直接初始化類的成員變量,但是我們一般不這么做,這樣初始化的方式不僅麻煩(假如每次創(chuàng)建多個對象時候,你就要多次使用對象.成員變量的方式初始化成員變量),而且破壞封裝的原則,我們希望的是一個類創(chuàng)建好,里面就直接幫我初始化了一些成員變量,所以搞出一個構(gòu)造函數(shù),為的就是初始化類里的成員變量。
這個構(gòu)造函數(shù),不是自己調(diào)用的,當然C++也規(guī)定不可以自己調(diào)用,是通過創(chuàng)建一個對象,該對象就會自動調(diào)用該類對象的構(gòu)造函數(shù)的(,這個操作是隱式操作,也就是說,是編譯器干的事情,你看不見,但是卻真實發(fā)生的事,相當于當你考試考了0分,怕爸媽看到不開心,自己偷偷的該為100分,這個改分的動作你爸媽也看不到;
關于自動調(diào)用構(gòu)造函數(shù)這個事:前提是該類有構(gòu)造函數(shù)或者沒有構(gòu)造函數(shù)的時候,當編譯器覺得你需要構(gòu)造函數(shù),編譯器就會給你一個默認構(gòu)造函數(shù)。這是一個專門要討論的話題,下面會討論一下。
在單參數(shù)構(gòu)造函數(shù)中,有一種初始化的方式為隱式初始化的方式。注意這種只能發(fā)生在單參數(shù)構(gòu)造函數(shù)中;
舉個例子:創(chuàng)建一個類,Person 類,該類如下,有個單參數(shù)的構(gòu)造函數(shù)。
#include #include using namespace std;class Person{public: int m_age; Person(int age) //單參數(shù)構(gòu)造函數(shù) { m_age = age; }};int main(){ //這里發(fā)生了10隱式轉(zhuǎn)化為Person的臨時對象, //從而調(diào)用了單參數(shù)的構(gòu)造函數(shù),構(gòu)造一個臨時對象初始化對象p1; Person p1 = 10; cout << p1.m_age << endl; //打印結(jié)果為10; return 0;}
上面你發(fā)現(xiàn)沒有,你可以用一個 為 int類型的 10 去初始化 類型為 Person 的 對象p1,明明這里不同的類型,卻初始化成功了,那說明,編譯器有能力偷偷的做了一些事情,把 10的int類型 轉(zhuǎn)化為 Person類型的能力。前提是,你的類中,必須有一個構(gòu)造函數(shù),該構(gòu)造函數(shù)可以使得編譯器做隱式類型轉(zhuǎn)換,這樣才會發(fā)生隱式類型轉(zhuǎn)化的初始化賦值。
編譯器是這樣轉(zhuǎn)化的:編譯器看到 10 和 p1 的類型不一致,那么該 10 就會轉(zhuǎn)化為 p1 類型,如何轉(zhuǎn)換呢?是在轉(zhuǎn)換的時候通過調(diào)用該類里面的單參數(shù)構(gòu)造函數(shù),產(chǎn)生了一個臨時對象,該臨時對象調(diào)用完單參數(shù)構(gòu)造函數(shù)時候(調(diào)用完了也就說明初始化完了這個臨時對象),聲明周期也就結(jié)束了,那么也就自然而然的銷毀了。該臨時對象是由于調(diào)用了單參數(shù)構(gòu)造函數(shù)產(chǎn)生的,所以類型是和p1一樣,所以這樣,就可以將臨時對象復制給p1了,對象復制時候,會把臨時對象的所有成員變量都一一的復制給p1;
從狹義上講,只要該類中有單參數(shù)的構(gòu)造函數(shù),就非常又可能在寫代碼時候,無意識的寫上這種隱式類型轉(zhuǎn)化的情況,比如在一個普通的函數(shù)中,該函數(shù)參數(shù)設計為類的形參,用一個非類的對象,即該變量可能和該類中的單參數(shù)構(gòu)造函數(shù)的參數(shù)類型相同,這里就會發(fā)生單參數(shù)的隱式構(gòu)造;
這種情況隱式構(gòu)造的發(fā)生是可以通過編譯的,但是我們并不推薦,因為這種方式,畢竟是不同類型的初始化方式,模糊不清,可讀性不好。
所以基于上面情況,我們有時候想有一種辦法,是強制編譯器不做隱式構(gòu)造,只能顯示的構(gòu)造(顯示的初始化)那就有一個關鍵字,explicit出場了。
這個explicit
是C++的一個關鍵字,該關鍵字用來修飾構(gòu)造函數(shù),使得該構(gòu)造函數(shù)不可以發(fā)生隱式類型轉(zhuǎn)換,必須顯示的初始化,或者顯示的類型轉(zhuǎn)換(即不是讓編譯器做偷偷轉(zhuǎn)換,即不是隱式轉(zhuǎn)換);
從 explicit
中文意思理解:明確的,清晰的;這樣就很好理解了,使得這個構(gòu)造函是明確的含義,清晰的表明它的作用,不要搞隱式構(gòu)造這種模糊的代碼。
舉個例子,在上面的單參數(shù)構(gòu)造函數(shù)前用explicit修飾,這就代表該構(gòu)造函數(shù)不可以發(fā)生隱式類型轉(zhuǎn)化構(gòu)造臨時變量。
#include #include using namespace std;class Person{public: int m_age; //單參數(shù)構(gòu)造函數(shù)前用explicit修飾, //這就代表該構(gòu)造函數(shù)不可以發(fā)生隱式類型轉(zhuǎn)化構(gòu)造臨時變量。 explicit Person(int age) { m_age = age; }};int main(){ Person p1 = 10; //嘗試隱式調(diào)用構(gòu)造函數(shù),錯誤 cout << p1.m_age << endl; //錯誤,調(diào)用失敗 return 0;}
上面的explicit很好的解決了單參數(shù)構(gòu)造函數(shù)不發(fā)生隱式構(gòu)造的方式,使得代碼含義更加清晰可讀;表現(xiàn)為:只要寫了隱式構(gòu)造的方式就會出錯;
explicit 不僅僅可以修飾單參數(shù)構(gòu)造函數(shù),也可以修飾多參數(shù)的構(gòu)造函數(shù),只不過不常用而已。
只要明確explicit是修飾構(gòu)造函數(shù),使得該構(gòu)造函數(shù)只能顯示初始化,和顯示類型轉(zhuǎn)換就行,反正就不可以發(fā)生隱式類型 轉(zhuǎn)換;
建議:單參數(shù)構(gòu)造函數(shù)都用 explicit 修飾.
一般來說,對于對象的初始化方式:
隱式初始化表現(xiàn)與代碼的形式:類類型 對象 = 變量(其他不與該類對象類型相同的變量,該變量與構(gòu)造函數(shù)的參數(shù)相同)
注意這里有個等號,一般有等號這種方式都會發(fā)生隱式構(gòu)造,隱式初始化;
顯示初始化表現(xiàn)與代碼的形式:沒有等號的方式 :如 類 對象 ()
;或者類型對象對應有等號的初始化方式: 類 對象 = 對象
;
還有一點,臨時對象不一定是隱式類型轉(zhuǎn)換發(fā)生的:
比如
Preson p2 = Perosn(10);這里就是構(gòu)造臨時對象顯示初始化 p2,但這里Perosn(10)構(gòu)建的臨時對象并沒有隱式轉(zhuǎn)換啊;
首先我們必須明確:構(gòu)造函數(shù)初始化列表的執(zhí)行順序是先于函數(shù)體的代碼滴。
舉個例子:比如我創(chuàng)建一個新的類:Student類
class Student{public: int m_age; int m_id; double m_score; //構(gòu)造函數(shù)初始化 Student(int age,int id,int score):m_age(age),m_id(id) { m_score = score; }};
上面的student在創(chuàng)建對象的時候,該對象里面的初始化列表中,m_age,m_id的執(zhí)行順序是先于m_score的,也就是說,先執(zhí)行的是初始化列表的代碼,再執(zhí)行函數(shù)體的代碼。
上面的案例也說明:對于構(gòu)造函數(shù)里面初始化成員變量有兩種方式:
第一種就是:初始化列表的方式初始化;第二種就是:在構(gòu)造函數(shù)體內(nèi)通過賦值語句初始化;這兩種初始化的方式是由本質(zhì)區(qū)別的,但是對于本案例中成員變量為內(nèi)置數(shù)據(jù)類型來說是沒多大關系,重點關注在函數(shù)體內(nèi)的賦值語句,這個賦值語句和初始化列表初始化方式對于內(nèi)置類型來說沒什么印象,但是對于類的成員變量,即不是內(nèi)置類型的成員變量,用初始化列表的方式會提升效率,這是因為在賦值語句初始化的時候,可能會調(diào)用一次或者多次類成員變量的構(gòu)造函數(shù)拷貝構(gòu)造函數(shù)等號賦值重載操作函數(shù)等,而初始化列表的方式卻不會,
這個話題話還會繼續(xù)講:到第二篇文章講它。
在C++11新標準中,我們是可以給類內(nèi)的成員變量賦初始值滴,當我們在創(chuàng)建對象的時候,這個初始值就用來初始化成員變量。假如沒有賦初始值的話,系統(tǒng)會提供默認初始化,比如:對于內(nèi)置類型的in的成員變量,沒有賦初始值,該成員變量的初始值是0xCCCCCC,即我們看到的隨機值;
舉個例子:在我們上面例子的Student類中,給 成員變量賦初始值:
int age = 10;//給成員變量age賦初始值;
如果給成員變量賦初始值的同時,還通過構(gòu)造函數(shù)初始化了改成員變量,那么構(gòu)造函數(shù)的成員變量就會覆蓋改初始值。
關于const成員變量,在構(gòu)造函數(shù)初始化時候,只能在參數(shù)列表初始化,不可以在函數(shù)體初始化。
當然,你也是可以通過類內(nèi)初始化的方式賦值初始化的,
舉個例子:
//關于const成員變量,在構(gòu)造函數(shù)初始化時候,只能在參數(shù)列表初始化,不可以在函數(shù)體初始化class A{public: A() :i(20) { //i = 20;// 有誤,不可以在構(gòu)造函數(shù)體初始化 } const int i = 10; //const int i;也是可以};A a; // 調(diào)用成功
為什么只能在構(gòu)造函數(shù)初始化類比初始化呢,而不能在函數(shù)體內(nèi)初始化呢?cosnt成員變量只有只讀的狀態(tài),你在函數(shù)體內(nèi)賦值,相當于是直接給const成員變量修改值了,所以只能從初始化列表初始化const成員變量;這其實也側(cè)面說明賦值和初始化確實是不同的。
當構(gòu)造函數(shù)不帶參數(shù)時,我們就把這個構(gòu)造函數(shù)叫做默認構(gòu)造函數(shù)。
比如對于這個Student類
class Student{public: int m_age; int m_id = 10010; //注意這里有初始值 double m_score; Student() //默認構(gòu)造函數(shù),也是無參構(gòu)造函數(shù) { m_age = 10; } };int main(){ Student s ; //成功創(chuàng)建對象,且調(diào)用了默認構(gòu)造函數(shù)初始化對象 return 0;}
當我給 Student s ;
打斷點,執(zhí)行該語句,看監(jiān)視窗口,發(fā)現(xiàn)該對象成功創(chuàng)建,并且調(diào)用了構(gòu)造函數(shù)初始化里面。
其實這是大家都懂這個道理,由于類有構(gòu)造函數(shù),創(chuàng)建對象肯定會調(diào)用構(gòu)造函數(shù)。
那假如我把構(gòu)造函數(shù)注釋掉,即我注釋掉上面Student 類的默認構(gòu)造函數(shù),當我以同樣的方式執(zhí)行上面的代碼: Student s
;你發(fā)現(xiàn),也成功啦。
看測試圖:
所以有個結(jié)論:
即使一個類沒有構(gòu)造函數(shù),那么也是可以成功創(chuàng)建對象的。
注意關鍵字眼,也是可以成功,我并沒有說一定成功 。
這也是我在上面關于自動調(diào)用構(gòu)造函數(shù)時候留下的話題,將在這里討論。
有人可能會認為,當我們沒有寫構(gòu)造函數(shù)時候,編譯器會給我們自動生成一個所謂的“合成默認構(gòu)造函數(shù),”在我們沒有給類寫構(gòu)造函數(shù)時候,創(chuàng)建對象能成功原因,是因為這個所謂的“合成默認構(gòu)造函數(shù).”。
其實這種想法是錯誤的???
其實這種想法是錯誤的???
其實這種想法是錯誤的???。
真正的理解是:
1. 即便一個類沒有寫構(gòu)造函數(shù),編譯器也不一定(但有些情況會)會給該類合成默認構(gòu)造函數(shù),對象依舊能夠成功創(chuàng)建。
2. 也就是說創(chuàng)建對象成功,不需要類中一定有構(gòu)造函數(shù),即使沒有也可以。
3. 一個類中,假如沒有寫構(gòu)造函數(shù),編譯器可能會合成默認構(gòu)造函數(shù),可能也不會合成默認構(gòu)造函數(shù),到底何不合成默認構(gòu)造函數(shù),這是取決于編譯器覺得是否是需要給你合成默認構(gòu)造函數(shù),當然不管需不需要合成,對象都是可以創(chuàng)建成功的,這是不會錯的。
但是有個問題就是:什么時候上面的對象才不會創(chuàng)建成功呢?
比如在該類,加了一個有參構(gòu)造函數(shù)
class Student{public: int m_age; int m_id = 10010; //注意這里有初始值 double m_score; //Student() //默認構(gòu)造函數(shù),也是無參構(gòu)造函數(shù) //{ // m_age = 10; //} Student(int age) { m_age = age; }};int main(){ Student s ; //創(chuàng)建失敗,嘗試調(diào)用無參的構(gòu)造函數(shù),但是沒有 return 0;}
在這種情況下,即自己寫了一個有參的構(gòu)造函數(shù),那么編譯器就不可能會為你合成默認構(gòu)造函數(shù)了,同時,假如你還是以Student s
這種方式創(chuàng)建對象的話,那就會失敗,因為你類提供了有參構(gòu)造函數(shù),沒有提供無參的構(gòu)造函數(shù),這個時候就會創(chuàng)建對象失敗。所以一個結(jié)論就是:當程序員自己書寫了構(gòu)造函數(shù)時候,那么你就要提供相應與書寫構(gòu)造函數(shù)相應形參的實參形式,才創(chuàng)建成功對象。
所以由這個結(jié)論引出上訴的創(chuàng)建方式會失敗,要想創(chuàng)建成功:
提供相應構(gòu)造函數(shù)形參的實參,即書寫這樣的代碼:
Student s (10); //成功創(chuàng)建對象,并且調(diào)用了單參數(shù)的構(gòu)造函數(shù)
回到我們剛剛的話題,即便一個類沒有書寫自己的構(gòu)造函數(shù)也是可以創(chuàng)建成功對象的。
還是回到剛剛的Student類的代碼,注釋掉單參數(shù)的構(gòu)造函數(shù),回到有默認構(gòu)造函數(shù)的時候。
class Student{public: int m_age; int m_id = 10010; //注意這里有初始值 double m_score; Student() //默認構(gòu)造函數(shù),也是無參構(gòu)造函數(shù) { m_age = 10; } //Student(int age) //{ // m_age = age; //}};int main(){ Student s ; //在沒有書寫自己的構(gòu)造函數(shù)時候,對象也是可以創(chuàng)建成功的 return 0;}
上訴的對象可以創(chuàng)建對象成功,我們也知道,但是我有個問題,就是上訴的代碼到底有沒有編譯器合成默認構(gòu)造函數(shù)呢?
這也是我們即將討論的話題,編譯器到底什么時候才會給我們合成默認構(gòu)造函數(shù)
我們看看上面的代碼情況,在沒有寫構(gòu)造函數(shù)的前提下,編譯器給這個Student類合成了一個默認構(gòu)造函數(shù),通過反匯編可以看到。
為什么這種情況會合成默認構(gòu)造函數(shù)呢?
原因是該類中有成員變量是賦了初始值的,你觀察Student
類,有一句成員變量的int m_id = 10010;
這句代碼使得編譯器沒有默認構(gòu)造函數(shù),給該Student
類合成了一個默認構(gòu)造函數(shù),是如何合成的?是因為有這句int m_id = 10010
;這個10010就會使得編譯器需要合成默認構(gòu)造函數(shù),注意是編譯器認為它需要滴,就在這個默認構(gòu)造函數(shù)中初始化這個 m_id 的成員變量;
假如我把上面的代碼int m_id = 10010;
注釋掉,即在Student
類沒有成員變量被賦初始值的了,同時也沒有構(gòu)造函數(shù),此時,你在 Student s
;這個創(chuàng)建變量代碼打一個斷點,你發(fā)現(xiàn),這句話直接跳過沒有執(zhí)行,當我門通過監(jiān)視發(fā)現(xiàn),雖然沒執(zhí)行但是卻實實在在的把對象創(chuàng)建成功;
其實沒執(zhí)行這句話的原因是因為,編譯器認為你沒有構(gòu)造構(gòu)造函數(shù), 也認為你不需要合成默認構(gòu)造函數(shù),所以給你直接跳過這個語句,不執(zhí)行,但是,監(jiān)視中,對象確實存在的,說明這個對象在沒有構(gòu)造函數(shù)的條件下,和編譯器沒有合成默認構(gòu)造函數(shù)的條件下,也成功創(chuàng)建了。
驗證一下代碼:
第二種情況:
當類中有虛函數(shù)的時候,自己不寫構(gòu)造函數(shù)時候,編譯器會合成默認構(gòu)造函數(shù)。
如:
class Student{public: int m_age; //int m_id = 10010; //注意這里有初始值 double m_score; virtual void fun() //類中有虛函數(shù),自己類不寫構(gòu)造函數(shù),編譯器會合成一個默認構(gòu)造函數(shù) { } //Student() //默認構(gòu)造函數(shù),也是無參構(gòu)造函數(shù) //{ // m_age = 10; //} //Student(int age) //{ // m_age = age; //}};int main(){ Student s ; return 0;}
我們給 Student s
打一個斷點,觀察反匯編:
為什么這種情況,即類中有虛函數(shù),沒有寫構(gòu)造函數(shù),編譯器會默認合成構(gòu)造函數(shù)?
因為,編譯器覺得需要合成默認構(gòu)造函數(shù),在我們創(chuàng)建對象時候,由于有虛函數(shù),那么該對象就會多出4個字節(jié),用于存放虛指針,該虛指針指向一個虛表,所以必須有該虛指針必須要有虛表的地址,那么該虛指針就必須初始化,那么對于編譯器來說,他覺得需要一個默認構(gòu)造函數(shù)來初始化該虛指針,即給該虛指針賦值虛表地址。
對于編譯器來說,只要他覺得需要給你的類一個構(gòu)造函數(shù),他就會合成一個構(gòu)造函數(shù)給你。
第三種情況:
當一個類有虛繼承的情況,該類沒有構(gòu)造函數(shù),則編譯器會合成一個默認構(gòu)造函數(shù)。
如:
class Person{ int m_price; };//stdent 類虛繼承了Peson類,該Student類假如沒有構(gòu)造函數(shù),則編譯器會合成一個默認的構(gòu)造函數(shù)class Student:public virtual Person{public: int m_age; double m_score; };int main(){ Student s ; return 0;}
我們給上面代碼 Student s ;
打一個斷點,發(fā)現(xiàn)編譯器合成了一個默認構(gòu)造函數(shù)。
如圖
為什么Students類虛繼承了Person類,該Student類沒有構(gòu)造函數(shù),編譯器會合成一個默認構(gòu)造函數(shù)呢?
原因:也是編譯器覺得有必要合成一個默認構(gòu)造函數(shù),因為子類虛繼承了父類,那么說明子類的對象中就多了4個字節(jié),該4個字節(jié)用來保存虛指針,該虛指針指向一個虛表,所以必須有該虛指針必須要有虛表的地址,那么該虛指針就必須初始化,那么對于編譯器來說,他覺得需要一個默認構(gòu)造函數(shù)來初始化該虛指針,即給該虛指針賦值虛表地址。
總的來說,還是編譯器覺得需要給你合成一個默認構(gòu)造函數(shù)。
第四種情況:
該類1包含了類2類型的成員變量,并且該類2中有構(gòu)造函數(shù),在類1沒有構(gòu)造函數(shù)的情況下,編譯器就會給類1合成默認構(gòu)造函數(shù)。
代碼如下:
class Person{public: int m_price; Person() { m_price = 10; }};class Student {public: int m_age; double m_score; Person p; //在Student 包含了Person 類的成員變量};int main(){ Student s; //成功創(chuàng)建對象,且調(diào)用了默認構(gòu)造函數(shù)初始化對象 return 0;}
驗證結(jié)果:
為什么在該類1包含了類2類型的成員變量,并且該類2中有構(gòu)造函數(shù),在類1沒有構(gòu)造函數(shù)的情況下,編譯器就會給類1合成默認構(gòu)造函數(shù)。
原因:因為編譯器認為需要有一個合成的默認構(gòu)造函數(shù)。對于該語句Student s;
在創(chuàng)建一個Student類對象時候,該對象沒有構(gòu)造函數(shù),但是編譯器也給它合成了構(gòu)造函數(shù),是因為該類有Person 類的成員變量,并且該Person類是有構(gòu)造函數(shù)的,所以編譯器認為需要Student類一個構(gòu)造函數(shù),去初始化該Person p;中的成員變量,該構(gòu)造函數(shù)里面是通過初始化列表調(diào)用Person 的構(gòu)造函數(shù)滴。所以編譯器會合成默認構(gòu)函數(shù)。
當然有一種衍生情況,父類中的成員變量有賦初始值,但是沒有構(gòu)造函數(shù),子類有該父類的成員變量,子類也沒有構(gòu)造函數(shù),在創(chuàng)建子類對象時候,也會給子類合成一個默認構(gòu)造函數(shù)滴。
總結(jié):
什么時候編譯器會給你合成默認構(gòu)造函數(shù)呢?
當編譯器覺得需要的時候就會給你合成默認構(gòu)造函數(shù),或者說當編譯器認為有事情要做的時候,是會合成一個默認構(gòu)造函數(shù)的。
但是總的來說,編譯器合成的默認構(gòu)造函數(shù)并不是什么好東西,即很多時候,并不能是你的意愿,該合成的構(gòu)造函數(shù)并不能按你想要的要求去做事;
我講這個話題,只是為了告訴你,當你創(chuàng)建一個
對象成功時候,不一定編譯器會給你合成默認構(gòu)造函數(shù)滴。
并不是讓你去使用編譯器合成默認構(gòu)造函數(shù),這個我們一般不推薦。
構(gòu)造函數(shù)還有很多話題沒聊完,但是我覺得篇幅太長,所以分開兩篇文章講。
下篇繼續(xù)來聊構(gòu)造函數(shù)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/118808.html
摘要:設計模式是以面向?qū)ο缶幊虨榛A的,的面向?qū)ο缶幊毯蛡鹘y(tǒng)的的面向?qū)ο缶幊逃行┎顒e,這讓我一開始接觸的時候感到十分痛苦,但是這只能靠自己慢慢積累慢慢思考。想繼續(xù)了解設計模式必須要先搞懂面向?qū)ο缶幊蹋駝t只會讓你自己更痛苦。 JavaScript 中的構(gòu)造函數(shù) 學習總結(jié)。知識只有分享才有存在的意義。 是時候替換你的 for 循環(huán)大法了~ 《小分享》JavaScript中數(shù)組的那些迭代方法~ ...
摘要:在使用原型鏈實現(xiàn)繼承時有一些需要我們注意的地方注意繼承后的變化。在了解原型鏈時,不要忽略掉在末端還有默認的對象,這也是我們能在所有對象中使用等對象內(nèi)置方法的原因。 在上一篇post中,介紹了原型的概念,了解到在javascript中構(gòu)造函數(shù)、原型對象、實例三個好基友之間的關系:每一個構(gòu)造函數(shù)都有一個守護神——原型對象,原型對象心里面也存著一個構(gòu)造函數(shù)的位置,兩情相悅,而實例呢卻又...
摘要:原型繼承基本模式這種是最簡單實現(xiàn)原型繼承的方法,直接把父類的對象賦值給子類構(gòu)造函數(shù)的原型,這樣子類的對象就可以訪問到父類以及父類構(gòu)造函數(shù)的中的屬性。 真正意義上來說Javascript并不是一門面向?qū)ο蟮恼Z言,沒有提供傳統(tǒng)的繼承方式,但是它提供了一種原型繼承的方式,利用自身提供的原型屬性來實現(xiàn)繼承。Javascript原型繼承是一個被說爛掉了的話題,但是自己對于這個問題一直沒有徹底理解...
摘要:方法完成回調(diào)注冊模式下,對象通過方法調(diào)用,注冊完成態(tài)和失敗態(tài)的回調(diào)函數(shù)。這些回調(diào)函數(shù)組成一個回調(diào)隊列,處理的值。調(diào)用實例的方法,能使注冊的回調(diào)隊列中的回調(diào)函數(shù)依次執(zhí)行。 之前寫了一篇關于ES6原生Promise的文章。近期又讀樸靈的《深入淺出Node》,里面介紹了一個Promise/Deferred模式。 Promise是解決異步問題的利器。它其實是一種模式。Promise有三種狀態(tài),...
摘要:當你用該日期類創(chuàng)建一個對象時,編譯器會自動調(diào)用該構(gòu)造函數(shù)對新創(chuàng)建的變量進行初始化。注意構(gòu)造函數(shù)的主要任務并不是開空間創(chuàng)建對象,而是初始化對象。編譯器對內(nèi)置類型使用默認構(gòu)造函數(shù)時,對其成員賦的是隨機值。 ...
閱讀 3043·2021-11-19 11:31
閱讀 3128·2021-09-02 15:15
閱讀 984·2019-08-29 17:22
閱讀 1058·2019-08-29 16:38
閱讀 2464·2019-08-26 13:56
閱讀 832·2019-08-26 12:16
閱讀 1434·2019-08-26 11:29
閱讀 929·2019-08-26 10:12