JavaScript垃圾回收與閉包舉例詳解
垃圾回收
標(biāo)記清除
當(dāng)變量進(jìn)入環(huán)境時(shí),將其標(biāo)記為“進(jìn)入環(huán)境”。當(dāng)變量離開環(huán)境時(shí),則將其標(biāo)記為“離開環(huán)境”。垃圾回收器會(huì)銷毀那些帶標(biāo)記的值,并回收它們所占用的內(nèi)存空間。
function test() {
var a = 1; // 函數(shù)調(diào)用時(shí) 被標(biāo)記 進(jìn)入上下文
}
test(); // 函數(shù)執(zhí)行完畢,a的標(biāo)記去掉,被回收
引用計(jì)數(shù)
當(dāng)聲明一個(gè)變量并將一個(gè)引用類型值賦給該變量時(shí),則這個(gè)值的引用次數(shù)就是1。如果同一個(gè)值又被賦給另一個(gè)變量,則該值的引用次數(shù)加1。相反,如果包含對(duì)這個(gè)值引用的變量又取得了另外一個(gè)值,則這個(gè)值的引用次數(shù)減1。當(dāng)這個(gè)值的引用次數(shù)變成0時(shí),則說(shuō)明沒(méi)有辦法再訪問(wèn)這個(gè)值了,因而就可以將其占用的內(nèi)存空間回收回來(lái)。當(dāng)垃圾回收器下次再運(yùn)行時(shí),它就會(huì)釋放那些引用次數(shù)為0的值所占用的內(nèi)存。
function test() {
var a = {}; // a的引用次數(shù)為0,被回收
var b = a; // a的引用次數(shù)加1,為1
var c = a; // a的引用次數(shù)再加1,為2
a = 1; // a的引用次數(shù)減1,為1
b = 1; // a的引用次數(shù)減1,為0,可以被回收了
c = 1; // a的引用次數(shù)減1,為0,可以被回收了
}
閉包
閉包是指有權(quán)訪問(wèn)另一個(gè)函數(shù)作用域中的變量的函數(shù)。創(chuàng)建閉包的常見方式,就是在一個(gè)函數(shù)內(nèi)部創(chuàng)建另一個(gè)函數(shù)。閉包使得函數(shù)可以繼續(xù)訪問(wèn)定義時(shí)的詞法作用域。
閉包的另一個(gè)用處,是封裝私有變量。
function createCounter() {
let count = 0;
return {
increment: function () {
count++;
},
getCount: function () {
return count;
},
};
}
const counter = createCounter();
counter.increment();
console.log(counter.getCount()); // 1
閉包的缺點(diǎn):
- 由于閉包會(huì)使得函數(shù)中的變量都被保存在內(nèi)存中,內(nèi)存消耗很大,所以不能濫用閉包,否則會(huì)造成網(wǎng)頁(yè)的性能問(wèn)題,在IE中可能導(dǎo)致內(nèi)存泄露。解決方法是,在退出函數(shù)之前,將不使用的局部變量全部刪除。
- 閉包會(huì)在父函數(shù)外部,改變父函數(shù)內(nèi)部變量的值。所以,如果你把父函數(shù)當(dāng)作對(duì)象(object)使用,把閉包當(dāng)作它的公用方法(Public Method),把內(nèi)部變量當(dāng)作它的私有屬性(private value),這時(shí)一定要小心,不要隨便改變父函數(shù)內(nèi)部變量的值。
- 閉包的缺點(diǎn)就是常駐內(nèi)存,會(huì)增大內(nèi)存使用量,并且使用不當(dāng)很容易造成內(nèi)存泄露。
閉包的用途
- 創(chuàng)建私有變量
function createCounter() { let count = 0; return { increment: function () { count++; }, getCount: function () { return count; }, }; } - 模擬塊級(jí)作用域
(function () { for (var i = 0; i < 10; i++) { console.log(i); } })(); - 實(shí)現(xiàn)柯里化
function add(a, b, c) { return a + b + c; } function curry(fn) { return function curried(...args) { if (args.length >= fn.length) { return fn.apply(this, args); } else { return function (...args2) { return curried.apply(this, args.concat(args2)); }; } }; } const curriedAdd = curry(add); console.log(curriedAdd(1)(2)(3)); // 6 - 實(shí)現(xiàn)函數(shù)節(jié)流和防抖
function throttle(fn, delay) { let timer = null; return function (...args) { if (!timer) { timer = setTimeout(() => { fn.apply(this, args); timer = null; }, delay); } }; } function debounce(fn, delay) { let timer = null; return function (...args) { clearTimeout(timer); timer = setTimeout(() => { fn.apply(this, args); }, delay); }; } - 實(shí)現(xiàn)單例模式
function Singleton(fn) { let instance = null; return function (...args) { if (!instance) { instance = new (fn.bind(this, ...args))(); } return instance; }; } function User(name) { this.name = name; } const createUser = Singleton(User); const user1 = createUser('Alice'); const user2 = createUser('Bob'); console.log(user1 === user2); // true - 實(shí)現(xiàn)模塊化開發(fā)
const module = (function () { let privateVar = 0; function privateFunc() { console.log('privateFunc'); } return { publicFunc: function () { console.log('publicFunc'); }, }; })(); module.publicFunc(); // publicFunc module.privateFunc(); // TypeError: module.privateFunc is not a function
總結(jié)
到此這篇關(guān)于JavaScript垃圾回收與閉包的文章就介紹到這了,更多相關(guān)JS垃圾回收與閉包內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS實(shí)現(xiàn)標(biāo)簽頁(yè)效果(配合css)
實(shí)現(xiàn)的效果是當(dāng)鼠標(biāo)移到某一個(gè)標(biāo)簽的時(shí)候,在下面的內(nèi)容區(qū)顯示對(duì)應(yīng)的內(nèi)容,并且相應(yīng)標(biāo)簽的顏色需要改變,這樣的效果是CSS和JS配合實(shí)現(xiàn)的,下面我們就來(lái)看看具體代碼2013-04-04
使用javaScript動(dòng)態(tài)加載Js文件和Css文件
這篇文章主要介紹了如何使用javaScript動(dòng)態(tài)加載Js文件和Css文件2015-10-10
javascript實(shí)現(xiàn)的淘寶旅行通用日歷組件用法實(shí)例
這篇文章主要介紹了javascript實(shí)現(xiàn)的淘寶旅行通用日歷組件,以實(shí)例形式分析了該日歷組件的相關(guān)設(shè)置及使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08
JavaScript中第三方庫(kù)Apollo的使用詳解
Apollo 是一個(gè)廣泛使用的 JavaScript 第三方庫(kù),主要用于構(gòu)建與 GraphQL API 交互的應(yīng)用程序,下面就跟隨小編一起來(lái)學(xué)習(xí)一下它的具體應(yīng)用吧2024-02-02
用Div仿showModalDialog模式菜單的效果的代碼
用Div仿showModalDialog模式菜單的效果的代碼...2007-03-03
詳解JavaScript的Date對(duì)象(制作簡(jiǎn)易鐘表)
這篇文章主要為大家詳細(xì)介紹了JavaScript的Date對(duì)象,和大家分享如何制作簡(jiǎn)易鐘表,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2015-12-12
JS跳出循環(huán)的方法區(qū)別對(duì)比分析(break,continue,return)
面向?qū)ο缶幊陶Z(yǔ)法中我們會(huì)碰到break ,continue, return這三個(gè)常用的關(guān)鍵字,那么關(guān)于這三個(gè)關(guān)鍵字的使用具體的操作是什么呢?接下來(lái)通過(guò)本文給大家講解JS跳出循環(huán)的方法區(qū)別對(duì)比分析(break,continue,return),感興趣的朋友一起看看吧2023-02-02

