程序de生命周期

個(gè)人開發(fā)總結(jié),不喜勿噴。

簡單聊一下程序中對(duì)象的生命周期。生命周期是一個(gè)對(duì)象/變量存在的有效時(shí)間端或區(qū)域中。任何對(duì)象包括靜態(tài)對(duì)象都被約束在一定范圍和周期內(nèi),只是靜態(tài)變量本身存在于整個(gè)程序的運(yùn)行周期中,不特別處理是不會(huì)被回收的。如果你想訪問這個(gè)對(duì)象/變量,你就需要在它的周期內(nèi)去訪問,而不要在其外部或等它死掉了再去訪問。

1. 塊內(nèi)

//函數(shù)方法內(nèi)
function t(){
  let a = 1;
}
//循環(huán)條件內(nèi)
for(let k in dic){
  let a = 1;
}
//空塊中
{
  let a = 1;
}

當(dāng)一個(gè)變量在函數(shù)、條件循環(huán)甚至空塊中,它的生命周期也只在這一范圍存在。

你會(huì)發(fā)現(xiàn)這套邏輯其實(shí)是面向過程開發(fā)的。 :P

2. 塊嵌套

{
  let b = 2;
  {
    let a = 1;
  }
  let c = 3;
}

在上面這樣的嵌套中,變量遵循創(chuàng)建之后和塊結(jié)束之前的訪問。在b點(diǎn)不可以訪問a和c的數(shù)值,在a點(diǎn)不可以訪問c的數(shù)值。在c點(diǎn)不可以訪問a的數(shù)值。在子括號(hào)結(jié)束后a會(huì)先于b被回收,整個(gè)代碼塊結(jié)束時(shí),b和c都會(huì)被回收。

發(fā)現(xiàn)了么,你在計(jì)算機(jī)課程中學(xué)到的入盞,出盞在這里體現(xiàn)了。最先被表達(dá)的塊在追后才被回收。遵循了先入后出的原則。 :P

3. 對(duì)象和對(duì)象中的子變量

class A{
  public type:number = 123;
  public static NUM = 1;
}

let a = new A();
console.log(a.type);
console.log(A.NUM);

類的構(gòu)建要先于其對(duì)象的創(chuàng)建,類只是描述對(duì)象如何構(gòu)造的一個(gè)工廠。類中靜態(tài)對(duì)象可在構(gòu)造后隨時(shí)調(diào)用,且不需要?jiǎng)?chuàng)建對(duì)象。

神說要有類,于是就有了面向?qū)ο蟆?/p>

4. 數(shù)組和字典

let pool = [obj1, obj2];
let dic = {a:1,pot:{x:0,y:9}};

當(dāng)被包含在數(shù)組/詞典中,這個(gè)對(duì)象會(huì)有活過塊限制的特權(quán)。比如

let pool = [];
{
  let a = new A;
  pool.push(a);
}

在塊中的對(duì)象a雖然被回收了(你在塊外是無法調(diào)取到的)。但這個(gè)對(duì)象本身被pool帶出了塊區(qū)域,只要在pool生命周期中,它就能保護(hù)a不會(huì)死去。

在解釋型語言中,指針功能被弱化的消失不見了,但它并不是不存在。你創(chuàng)建的每個(gè)對(duì)象,其實(shí)都不是對(duì)象內(nèi)存本身,而是一個(gè)指向此對(duì)象的一個(gè)引用/指針/連結(jié)。在上面這個(gè)代碼中,系統(tǒng)在你看不到的后臺(tái)創(chuàng)建了new A的內(nèi)存對(duì)象地址p,然后將p連結(jié)給了a,a又把p的地址告訴了pool,a的使命完結(jié)掛掉了,但pool還是知道p的信息,知道它在哪里,所以它是安全的,直到pool死去,整個(gè)世界再也沒人知道p的存在,然后就等待著消亡。

5. 奇怪的時(shí)空跳躍 - 匿名函數(shù)與lamda表達(dá)式

function getData(params){
    let request = new NetWork("http://urlxxxxx");//瞎寫的
    request.send("post",params).then(()=>{
        console.log(params);
    }).cache(()=>{
        console.log(params);
    })
}

你會(huì)發(fā)現(xiàn)奇怪的現(xiàn)象,params竟然活到了send接口溝通結(jié)束以后,太神奇了,為什么它能持續(xù)這么久,明明這個(gè)getData函數(shù)早已執(zhí)行完畢,但它的生命周期被延續(xù)了。

那是因?yàn)閘amda表達(dá)式對(duì)對(duì)象的引用做了連結(jié),其實(shí)原本params已經(jīng)死去了,只是在lamda式子中它被復(fù)制了一份連結(jié),而且每個(gè)lamda的復(fù)制是單獨(dú)的,他們雖然指向相同的參數(shù),但是從原理上最后兩個(gè)輸出是不一樣的(結(jié)果是一樣的)。

6. 函數(shù)為什么要指明對(duì)象

class A{
  function getP():number{ return 0;}
}

function laterCall(obj, func){
  func.call(obj); // or apply(obj);
}

一般來講函數(shù)是調(diào)用時(shí)直接執(zhí)行的,有時(shí)候我們需要操作一些其他函數(shù)處理結(jié)果完畢后再調(diào)用此函數(shù),有時(shí)候需要等待一定時(shí)間來響應(yīng)他,有時(shí)候需要網(wǎng)絡(luò)的反饋來決定是否要激活這個(gè)函數(shù)。那為什么要寫函數(shù)和對(duì)象呢?

首相非直接調(diào)用函數(shù)并非必須使用對(duì)象,全局函數(shù)就不需要。其次函數(shù)本身的編號(hào)是對(duì)應(yīng)對(duì)象的,而不是全局,這也是為了索引效率(其實(shí)全局變量也是這么設(shè)計(jì)的,把全局看成一個(gè)對(duì)象)。 :p

7. 打印函數(shù)所出現(xiàn)的有趣奇特現(xiàn)象 (h5開發(fā))

let a = {p:{c:1}}
console.log(a);
a.p = null;

當(dāng)你想打印a的整個(gè)對(duì)象的時(shí)候,你會(huì)發(fā)現(xiàn),控制臺(tái)的輸出變成了p為null的結(jié)果。這是因?yàn)檩敵龅臅r(shí)候記錄的是對(duì)a這個(gè)對(duì)象的連結(jié),它是動(dòng)態(tài)的,尤其內(nèi)部是有對(duì)象變化的情況。

有時(shí)候你會(huì)發(fā)現(xiàn)這樣讓你輸出很混亂,這樣的時(shí)候你就做個(gè)遍歷對(duì)象輸出就好了,注意避免代碼影響發(fā)布。

8. 斬?cái)嗌?/h4>
let a = {p:{c:1}}
delete a.p;

創(chuàng)建一個(gè)a對(duì)象,它能保護(hù)p對(duì)象不會(huì)死掉,那么怎么能斬?cái)噙@種保護(hù).

delete可以去掉對(duì)象之間的連結(jié),但無法去掉類對(duì)象和內(nèi)部變量的連結(jié)。(少用delete,他并不能多幫你回收多少內(nèi)存,但可能會(huì)給你埋很多雷)

8. 死亡和回收

當(dāng)各種對(duì)象,變量等不再被任何程序運(yùn)行時(shí)引用,他就處于休眠狀態(tài)。這時(shí)的對(duì)象并沒有完全死掉。也就是說如果這個(gè)對(duì)象和外部沒有溝通,但是內(nèi)部還在運(yùn)轉(zhuǎn),那么也有可能影響到程序的運(yùn)行,比如用觀察者模式的時(shí)候,刪除對(duì)象但是忘了移除notification事件,由于觀察者靈活度高耦合度低的特點(diǎn),這個(gè)對(duì)象可能會(huì)產(chǎn)生詐尸或者干擾游戲正常運(yùn)行等各種問題。
等待一定時(shí)間系統(tǒng)就會(huì)自動(dòng)回收這些垃圾,但是雖然說是回收,但并不等同于內(nèi)存的完美釋放。

當(dāng)對(duì)象被移除,有時(shí)候他連結(jié)了其他活躍的對(duì)象,雖然死了,但是還掙扎著不想被消滅。這樣的對(duì)象積累多了,你的內(nèi)存就慢慢的漫出來了,然后系統(tǒng)/軟件就會(huì)崩潰掉。

9. 盡量做到重復(fù)利用

提倡以下幾點(diǎn):

  1. 值不變就用常量const
  2. 盡量用單例來代替靜態(tài)類函數(shù)。
  3. 能不創(chuàng)建就不創(chuàng)建,能少創(chuàng)建就少創(chuàng)建對(duì)象。
  4. 重復(fù)利用已有的對(duì)象來反復(fù)發(fā)揮效率。
  5. 在循環(huán)外創(chuàng)建局部變量

題外話,關(guān)于效率再加兩句:能用乘法就少用除法,能用加減乘除就少用三角函數(shù)開方操作等,應(yīng)該再開一個(gè)坑單獨(dú)寫一下,以后再說吧。

創(chuàng)建是要耗費(fèi)內(nèi)存,cpu和時(shí)間的,節(jié)省下來的話,你也可以增快你的程序運(yùn)行速度。

請(qǐng)大家多多提意見

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容