個(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;
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):
- 值不變就用常量const
- 盡量用單例來代替靜態(tài)類函數(shù)。
- 能不創(chuàng)建就不創(chuàng)建,能少創(chuàng)建就少創(chuàng)建對(duì)象。
- 重復(fù)利用已有的對(duì)象來反復(fù)發(fā)揮效率。
- 在循環(huán)外創(chuàng)建局部變量
題外話,關(guān)于效率再加兩句:能用乘法就少用除法,能用加減乘除就少用三角函數(shù)開方操作等,應(yīng)該再開一個(gè)坑單獨(dú)寫一下,以后再說吧。
創(chuàng)建是要耗費(fèi)內(nèi)存,cpu和時(shí)間的,節(jié)省下來的話,你也可以增快你的程序運(yùn)行速度。
請(qǐng)大家多多提意見