成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

JS中對(duì)內(nèi)存的一些了解

elliott_hu / 414人閱讀

摘要:中對(duì)內(nèi)存的一些了解在進(jìn)行開發(fā)的過程中了解內(nèi)存機(jī)制有助于開發(fā)人員能夠清晰的認(rèn)識(shí)到自己寫的代碼在執(zhí)行的過程中發(fā)生過什么也能夠提高項(xiàng)目的代碼質(zhì)量內(nèi)存是怎么樣的中變量存放有著原始值與引用值之分原始值原始的數(shù)據(jù)類型以及新加入的引用值等類型的值便是引用

JS中對(duì)內(nèi)存的一些了解
在JS進(jìn)行開發(fā)的過程中, 了解JS內(nèi)存機(jī)制有助于開發(fā)人員能夠清晰的認(rèn)識(shí)到自己寫的代碼在執(zhí)行的過程中發(fā)生過什么, 也能夠提高項(xiàng)目的代碼質(zhì)量.
JS內(nèi)存是怎么樣的?

JS中變量存放有著原始值與引用值之分:

原始值: 原始的數(shù)據(jù)類型: undefinednull、numberstring、boolean以及es6新加入的symbol.

引用值: object、array、function等類型的值便是引用值.

JS中的內(nèi)存也分為棧內(nèi)存和堆內(nèi)存. 堆與棧 詳細(xì)了解查看這里.
eg:

const str = "我是說明內(nèi)存的文檔"; // 這里 str 以及 "我的說明內(nèi)存的文檔" 都存儲(chǔ)在棧內(nèi)存當(dāng)中
const obj = { a: 1 }; // 這里 obj(指向存儲(chǔ)在堆中的數(shù)據(jù)的指針) 是存儲(chǔ)在棧內(nèi)存 而 { a: 1 } 則存儲(chǔ)在堆當(dāng)中
內(nèi)存中的存儲(chǔ)對(duì)象聲明周期是怎么樣的呢?

MDN中的介紹:

當(dāng)對(duì)象將被需要的時(shí)候?yàn)槠浞峙鋬?nèi)存.

使用已分配的內(nèi)存(讀、寫操作)

當(dāng)對(duì)象不再被需要的時(shí)候, 釋放存儲(chǔ)這個(gè)對(duì)象的內(nèi)存

1 2在所有語言中都是一樣的, 3在JS當(dāng)中不是那么明顯

看看內(nèi)存中發(fā)生了什么?
let str1 = 1; // 為str1分配棧內(nèi)存 str1: 1
let str2 = str1; // 原始類型直接訪問值, 即為str2新分配棧內(nèi)存: str2: 1

str2 = 2; // 棧內(nèi)存: str2: 2. str2的值為2, 而str1的值仍然是1

/************************ 我是分割線: 上面為原始類型 下面為復(fù)雜類型 *******************************/

let obj1 = { a: 1 }; // 為obj1分為棧內(nèi)存訪問地址的指針: obj1. 堆內(nèi)存中存儲(chǔ)對(duì)象值: { a: 1 }
let obj2 = obj1; // 為obj2分配棧內(nèi)存訪問地址的指針: obj2. 引用了堆內(nèi)存中的值{ a: 1 }

obj2.a = 2; // 通過obj1修改堆內(nèi)存的數(shù)據(jù), 由于obj2與obj2都是指向堆內(nèi)存中的同一個(gè)數(shù)據(jù)的指針(也叫引用). 所以堆內(nèi)存中的值{a: 1}修改為{a: 2} 即 obj1.a 為 2; obj2.a 也為 2; (這里它們是指向了堆內(nèi)存中的同一個(gè)數(shù)據(jù)的不同指針)

obj2 = { a: 3 }; // 因?yàn)楦牡氖钦麄€(gè)對(duì)象, 這里會(huì)在堆內(nèi)存中創(chuàng)建一個(gè)新的對(duì)象值: {a:3}, 而obj2引用的是這個(gè)新對(duì)象, 所以obj1.a 依舊為 2; 而obj2.a 則為 3了. (這里它們是指向了堆內(nèi)存中的不同數(shù)據(jù)的不同的指針)

然后看看這個(gè)問題:

let a = { n: 1 };
let b = a;
a.x = a = { n: 2 };

具體查看詳細(xì)解釋, 對(duì)理解基礎(chǔ)知識(shí)點(diǎn)還是很有幫助的. 例如: js的賦值運(yùn)算順序永遠(yuǎn)都是從右往左的,但是.是優(yōu)先級(jí)最高的運(yùn)算符.

從內(nèi)存角度看函數(shù)傳值的變化

關(guān)于傳值/址的解說. 用原始類型和引用類型來區(qū)分. 原始類型傳的是值, 引用類型傳的則為址.

let str = "我是初始字符串";
let fn = (arg) => {
    console.log(arg); // #1 我是初始字符串

    arg = "我是修改后的字符串";
    console.log(arg); // #2 我是修改后的字符串
    console.log(str); // #3 我是初始字符串
};
fn(str);

上面例子#1可以看到傳入fn的是str的值, 在棧內(nèi)存中分配了新的空間來保存函數(shù)參數(shù)和其值(函數(shù)運(yùn)行后自動(dòng)釋放這部分內(nèi)存, _垃圾回收機(jī)制_). 所以在#2出輸出的值為我是修改后的字符串. 在調(diào)用函數(shù)fn時(shí)給參數(shù)arg傳了值(在棧內(nèi)存中新分配的數(shù)據(jù)), 而str又為原始類型. 在#3處輸出與初始化定義保持一致.

let obj = { a: 1 };
let fn = (arg) => {
    arg = { a: 2 };
};

fn(obj);
// 這個(gè)時(shí)候obj還是{a: 1}

let fn1 = (arg) => {
    arg.a = 2;
};
fn1(obj);
// 這個(gè)時(shí)候obj則為{a: 2}

上面這個(gè)例子中的兩個(gè)函數(shù)都是傳址, 起初傳入的參數(shù)arg都是引用(指向堆內(nèi)存中的同一個(gè)數(shù)據(jù)的指針), 在fn中重新為變量arg賦值新的對(duì)象(引用類型). 而在fn1中的arg依舊是引用(指向堆內(nèi)存中數(shù)據(jù)的指針), 所以fn1中是修改成功的.

垃圾回收機(jī)制

JS具有垃圾回收機(jī)制, 這給開發(fā)人員帶來了極大的方便, 至少不用太考慮內(nèi)存釋放的問題(有部分還是要考慮的).

函數(shù)的變量只在函數(shù)執(zhí)行過程中存在. 在函數(shù)執(zhí)行過程中, 函數(shù)內(nèi)部的變量將會(huì)在內(nèi)存中分配一定的空間, 當(dāng)函數(shù)執(zhí)行完畢后, 自動(dòng)將這些變量從內(nèi)存中釋放, 以留出空間作其它用處.

當(dāng)內(nèi)存中某個(gè)變量不再被引用, JS將清理掉這部分內(nèi)存的分配. eg:

let obj = { a: 1 }; // 內(nèi)存中存在{a: 1}對(duì)象, 以及obj這個(gè)引用地址
obj = { a: 2 }; // 垃圾回收機(jī)制自動(dòng)清理{a: 1}, 并為新的有用的{a: 2}分配空間
內(nèi)存優(yōu)化

就全局變量而言, JS不能確定它在后面是否用到, 所有它從聲明之后就一直存在于內(nèi)存中, 直至手動(dòng)釋放或者關(guān)閉頁面/瀏覽器, 這就導(dǎo)致了某些不必要的內(nèi)存消耗. 我們可以進(jìn)行以下優(yōu)化.
使用立即執(zhí)行函數(shù)

(() => {
    // do something...
})();

手動(dòng)接觸變量的引用

let obj = { a: 1, b: 2, c: 3 };
obj = null;

在JS中, 閉包是最容易產(chǎn)生內(nèi)存問題的, 我們可以使用回調(diào)函數(shù)代替閉包來訪問內(nèi)部變量. 使用回調(diào)的好處就是(針對(duì)訪問的內(nèi)部變量時(shí)原始類型的值, 因?yàn)樵诤瘮?shù)傳參的時(shí)候傳的是值), 在執(zhí)行后會(huì)自動(dòng)釋放其中的變量, 不會(huì)像閉包一樣一直將內(nèi)部變量存在于內(nèi)存中(但如果是引用類型, 那么這個(gè)被引用的對(duì)象依舊在內(nèi)存中).

function fn() {
    var val = "你好";
    return function() {
            return val
        };
};
var getVal = fn();
var v = getVal(); // 你好

上面例子中, 雖然函數(shù)fn已經(jīng)執(zhí)行完畢, 但是對(duì)于函數(shù)中變量val的引用還在, 所以垃圾回收機(jī)制不會(huì)將函數(shù)中的val回收.

使用回調(diào)

function fn1(cb) {
    var val = "你好";
    return cb(val);
};
function fn2(arg) {
    return arg;
};
var v = fn1(fn2);

同時(shí)聲明, 并不是說明這樣做就一定比閉包好, 閉包也有其好處, 只是需要我們?cè)诜智逶谧钋‘?dāng)?shù)臅r(shí)候使用.

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/108255.html

相關(guān)文章

  • JavaScript對(duì)內(nèi)存的使用

    摘要:內(nèi)存圖示意圖內(nèi)存圖就是簡化模擬示意使用的內(nèi)存中的數(shù)據(jù)區(qū)中的情況,簡單的分為棧內(nèi)存堆內(nèi)存,如下圖。明顯,左邊是原始代碼,中間是棧內(nèi)存,右邊是堆內(nèi)存。如果原始代碼中變量是對(duì)象,棧內(nèi)存中就會(huì)存儲(chǔ)堆內(nèi)存的地址隨機(jī),堆內(nèi)存中會(huì)存儲(chǔ)這個(gè)對(duì)象的所有內(nèi)容。 內(nèi)存的分配(示意) 啟動(dòng)程序,就需要分配內(nèi)存給運(yùn)行的程序。啟動(dòng)瀏覽器,就會(huì)分配一定內(nèi)存供瀏覽器使用,瀏覽器在會(huì)分配相應(yīng)的內(nèi)存供諸如HTML+CSS...

    Eastboat 評(píng)論0 收藏0
  • 三個(gè)閉包實(shí)例理解閉包對(duì)內(nèi)存的影響

    摘要:在試圖弄清這個(gè)問題之前,先要理解棧內(nèi)存堆內(nèi)存和預(yù)處理。因此在子函數(shù)執(zhí)行的時(shí)候,堆內(nèi)存被占用了,相應(yīng)的棧內(nèi)存也將保留。所以,棧內(nèi)存在執(zhí)行完之后會(huì)被保留一段時(shí)間,這段時(shí)間等于其子函數(shù)執(zhí)行的時(shí)間。 在試圖弄清這個(gè)問題之前,先要理解棧內(nèi)存、堆內(nèi)存和預(yù)處理。 占用內(nèi)存,不會(huì)銷毀的閉包實(shí)例 例1: var num = 12; function fn() { var num = 100; ...

    jackzou 評(píng)論0 收藏0
  • 理解 typed array

    摘要:在內(nèi)部設(shè)計(jì)時(shí)分成了兩部分和。層表示內(nèi)存中的數(shù)據(jù)塊,負(fù)責(zé)提供操作數(shù)據(jù)塊的接口。也就是說通過創(chuàng)建內(nèi)存塊,通過實(shí)現(xiàn)對(duì)內(nèi)存塊的讀寫操作。很顯然中的結(jié)果是。有同學(xué)可能對(duì)輸出的順序不理解,覺得為什么不是呢。上例在小端模式下的存儲(chǔ)形式,每個(gè)框框表示位。 我們知道在C語言中,可以使用malloc和free方法來分配和釋放內(nèi)存。隨著web的發(fā)展中,js在ES6中新增了內(nèi)存操作的支持。其實(shí)現(xiàn)方式就是---...

    _Zhao 評(píng)論0 收藏0
  • Java并發(fā)編程-原子類實(shí)現(xiàn)

    摘要:前言為了研究對(duì)原子類的實(shí)現(xiàn),從類開始,分析如果對(duì)原子操作的實(shí)現(xiàn)。保存著基礎(chǔ)數(shù)據(jù),使用修飾,可以保證該值對(duì)內(nèi)存可見,也是原子類實(shí)現(xiàn)的理論保障。使用自旋鎖來處理并發(fā)問題。 前言 為了研究Java對(duì)原子類的實(shí)現(xiàn),從AtomicInteger類開始,分析Java如果對(duì)原子操作的實(shí)現(xiàn)。 什么是原子操作? 原子操作是指不會(huì)被線程調(diào)度機(jī)制打斷的操作;這種操作一旦開始,就一直運(yùn)行到結(jié)束,中間不會(huì)有任何...

    gyl_coder 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<