成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

《JavaScript高級(jí)程序設(shè)計(jì)》(第3版)讀書(shū)筆記 第4章 變量、作用域和內(nèi)存問(wèn)題

lidashuang / 3549人閱讀

摘要:具體說(shuō)就是執(zhí)行流進(jìn)入下列任何一個(gè)語(yǔ)句時(shí),作用域鏈就會(huì)得到加長(zhǎng)語(yǔ)句的塊。如果局部環(huán)境中存在著同名的標(biāo)識(shí)符,就不會(huì)使用位于父環(huán)境中的標(biāo)識(shí)符訪(fǎng)問(wèn)局部變量要比訪(fǎng)問(wèn)全局變量更快,因?yàn)椴挥孟蛏纤阉髯饔糜蜴湣?/p>

基本類(lèi)型和引用類(lèi)型的值

ECMAscript變量包含 基本類(lèi)型值和引用類(lèi)型值

基本類(lèi)型值值的是基本數(shù)據(jù)類(lèi)型:Undefined, Null, Boolean, Number, String

引用類(lèi)型值是保存在內(nèi)存空間中的對(duì)象,與其他JavaScript不允許直接訪(fǎng)問(wèn)內(nèi)存中的位置,即不能直接操作對(duì)象的內(nèi)存空間,在操作對(duì)象時(shí),實(shí)際上是在操作對(duì)象的引用而不是實(shí)際的對(duì)象;為此,引用類(lèi)型的值是按引用訪(fǎng)問(wèn)的

在很多語(yǔ)言中,字符串以對(duì)象 的形式來(lái)表示,因此被認(rèn)為是引用類(lèi)型的,ECMAScript放棄了這一傳統(tǒng)

動(dòng)態(tài)的屬性

引用類(lèi)型的值可以為其添加屬性和方法,也可以改變和刪除屬性和方法

基本類(lèi)型值不行

var person = new Object();
person.name = "Nicholas";
alert(person.name);        // "Nicholas"

var person = "Nicholas";
person.age = 27;
alert(person.age);        // undefined
復(fù)制變量值

在從一個(gè)變量復(fù)制向另一個(gè)變量復(fù)制值時(shí),基本類(lèi)型值和引用類(lèi)型值存在不同

基本類(lèi)型值會(huì)在變量對(duì)象上創(chuàng)建一個(gè)新值,然后把該值復(fù)制到為新變量分配的位置上,兩個(gè)變量可以參與任何操作而不會(huì)互相影響

引用類(lèi)型也會(huì)復(fù)制一個(gè)副本放到新變量中,但這個(gè)副本實(shí)際上是一個(gè)指針,這個(gè)指針指向存儲(chǔ)在堆中的一個(gè)對(duì)象,復(fù)制操作結(jié)束后,兩個(gè)變量實(shí)際上將引用同一個(gè)對(duì)象,因此改變其中一個(gè)變量,就會(huì)影響另一個(gè)變量

var obj1 = new Object();
var obj2 = obj1;
obj1.name = "Nicholas";
alert(obj2.name);        // "Nicholas"
傳遞參數(shù)

ECMAscript中所有函數(shù)的參數(shù)都是按值傳遞的,即把函數(shù)外部的值復(fù)制給函數(shù)內(nèi)部的參數(shù),就和把值從一個(gè)變量復(fù)制到另一個(gè)變量一樣

在向參數(shù)傳遞基本類(lèi)型的值時(shí),被傳遞的值會(huì)被復(fù)制給一個(gè)局部變量(即為命名參數(shù),或者用ECMAScript的概念來(lái)說(shuō),就是函數(shù)的arguments對(duì)象中的一個(gè)元素)

在向參數(shù)傳遞引用類(lèi)型的值時(shí),會(huì)把這個(gè)值在內(nèi)存中的地址復(fù)制給一個(gè)局部變量,因此這個(gè)局部變量的變化會(huì)反映在函數(shù)外部

可以把ECMAScript的參數(shù)想象成局部變量

// 參數(shù)num是函數(shù)的局部變量
// 調(diào)用這個(gè)函數(shù)時(shí),變量count作為參數(shù)被傳遞給函數(shù),是將count的值20復(fù)制給參數(shù)num
// 在函數(shù)內(nèi)部,參數(shù)num的值加上了10,但不會(huì)影響函數(shù)外部的count變量,count和num互不影響
function addTen(num) {
    num += 10;
    return num;
}
var count = 20;
var result = addTen(count);
alert(count);        // 20, 沒(méi)有變化
alert(result);       // 30
// 以下為個(gè)人理解,原著表述不清楚不能直觀理解
// 傳遞給參數(shù)obj的實(shí)際上是指向person對(duì)象內(nèi)存地址(指針),是將地址復(fù)制了一個(gè)副本賦值給了參數(shù)obj
// 當(dāng)在函數(shù)內(nèi)部為obj添加name屬性后,函數(shù)內(nèi)部根據(jù)地址操作了內(nèi)存中的相應(yīng)對(duì)象,函數(shù)外部的person也將有反映
// 因?yàn)閜erson指向的對(duì)象在堆內(nèi)存中只有一個(gè),而且是全局對(duì)象
function setName(obj) {
    obj.name = "Nicholas";
}
var person = new Object();
setName(person);
alert(person.name);        // "Nicholas"

// 下列代碼,直覺(jué)認(rèn)為會(huì)alert出"Greg",但卻是"Nicholas"
// 因?yàn)閭鬟f給參數(shù)obj的只是指針的副本,當(dāng)函數(shù)內(nèi)重新給obj賦值的時(shí)候,實(shí)際上是將一個(gè)新的Object對(duì)象的指針賦給obj
// 此時(shí)操作obj影響的是新的Object對(duì)象,而person對(duì)象不受影響
// obj指向的新Object對(duì)象在函數(shù)執(zhí)行完后會(huì)立即銷(xiāo)毀
function setName(obj) {
    obj.name = "Nicholas";
    obj = new Object();
    obj.name = "Greg";
}
var person = new Object();
setName(person);
alert(person.name);        // "Nicholas"
檢測(cè)類(lèi)型

typeof操作符是確定一個(gè)變量是不是基本數(shù)據(jù)類(lèi)型的最佳工具

null和對(duì)象 typeof都會(huì)返回"object"

檢測(cè)引用類(lèi)型的值,instanceof操作符是最佳工具

根據(jù)規(guī)定,所有引用類(lèi)型的值都是Object的實(shí)例。因此在檢測(cè)一個(gè)引用類(lèi)型值和Object構(gòu)造函數(shù)時(shí),instanceof操作符始終返回true。如果使用instanceof操作符檢測(cè)基本類(lèi)型的值,返回false,因?yàn)榛绢?lèi)型不是對(duì)象

typeof 檢測(cè)函數(shù)會(huì)返回"function".在Safari 5 及 之前版本 Chrome 7 及 之前版本中使用typeof檢測(cè)正則表達(dá)式,也返回"function",ECMA-262規(guī)定任何在內(nèi)部實(shí)現(xiàn)[[call]]方法的對(duì)象都應(yīng)該在應(yīng)用typeof操作符時(shí)返回"function",由于上述瀏覽器中的正則表達(dá)式也實(shí)現(xiàn)了這個(gè)方法,因此對(duì)正則表達(dá)式應(yīng)用typeof會(huì)返回"function"。其他瀏覽器返回"object".

執(zhí)行環(huán)境及作用域

執(zhí)行環(huán)境(execution context,為簡(jiǎn)單起見(jiàn),有時(shí)也成為“環(huán)境”)是JavaScript中最為重要的一個(gè)概念

每個(gè)執(zhí)行環(huán)境都有一個(gè)與之關(guān)聯(lián)的變量對(duì)象(variable object),環(huán)境中定義的所有變量和函數(shù)都保存在這個(gè)對(duì)象中。

雖然編寫(xiě)的代碼無(wú)法訪(fǎng)問(wèn)這個(gè)對(duì)象,但解析器在處理數(shù)據(jù)時(shí)會(huì)在后臺(tái)使用它

全局執(zhí)行環(huán)境是最外圍的一個(gè)執(zhí)行環(huán)境。在web瀏覽器中,全局執(zhí)行環(huán)境被認(rèn)為是window對(duì)象,因此所有全局變量和函數(shù)都是作為window對(duì)象的屬性和方法創(chuàng)建的

某個(gè)執(zhí)行黃精中的所有代碼執(zhí)行完畢后,該環(huán)境被銷(xiāo)毀,保存在其中的所有變量和函數(shù)定義也隨之銷(xiāo)毀(全局執(zhí)行環(huán)境直到應(yīng)用程序退出——例如關(guān)閉網(wǎng)頁(yè)或?yàn)g覽器——時(shí)才會(huì)被銷(xiāo)毀)

每個(gè)函數(shù)都有自己的執(zhí)行環(huán)境。當(dāng)執(zhí)行流進(jìn)入一個(gè)函數(shù)時(shí),函數(shù)的環(huán)境就會(huì)被推入一個(gè)環(huán)境棧中,函數(shù)執(zhí)行完畢后,棧將其環(huán)境彈出,把控制權(quán)返回給之前的執(zhí)行環(huán)境

當(dāng)代嗎在一個(gè)環(huán)境中執(zhí)行時(shí),會(huì)創(chuàng)造變量對(duì)象的一個(gè)作用域鏈(scope chain)。作用域鏈的用途,是保證對(duì)執(zhí)行環(huán)境有權(quán)訪(fǎng)問(wèn)的所有變量和函數(shù)有序的訪(fǎng)問(wèn)

作用域鏈最前端始終是當(dāng)前執(zhí)行的代碼所在環(huán)境的變量對(duì)象,如果這個(gè)環(huán)境是函數(shù),則將其活動(dòng)對(duì)象(activation object)作為變量對(duì)象,活動(dòng)對(duì)象在最開(kāi)始時(shí)只包含一個(gè)變量,即arguments對(duì)象(這個(gè)對(duì)象在全局環(huán)境中是不存在的)。作用域鏈的最后一個(gè)對(duì)象始終都是全局執(zhí)行環(huán)境的變量對(duì)象

標(biāo)識(shí)符解析是沿著作用域鏈一級(jí)一級(jí)的搜索標(biāo)識(shí)符的過(guò)程,從最前端開(kāi)始,然后逐級(jí)向后回溯,直到找到標(biāo)識(shí)符為止(找不到通常會(huì)發(fā)生錯(cuò)誤)

// 函數(shù)changeColor()的作用域鏈包含兩個(gè)對(duì)象:
// 它自己的變量對(duì)象(其中定義著arguments對(duì)象)和全局環(huán)境的變量對(duì)象
var color = "blue";

function changeColor() {
    if (color === "blue") {
        color = "red";
    } else {
        color = "blue";
    }
}

changeColor();

alert("color is now " + color);        // "red"
延長(zhǎng)作用域鏈

有些語(yǔ)句尅在作用域鏈的前端臨時(shí)增加一個(gè)變量對(duì)象,該變量對(duì)象會(huì)在代碼執(zhí)行后被移除。具體說(shuō)就是執(zhí)行流進(jìn)入下列任何一個(gè)語(yǔ)句時(shí),作用域鏈就會(huì)得到加長(zhǎng)

try-catch 語(yǔ)句的catch塊。catch語(yǔ)句會(huì)創(chuàng)建一個(gè)新的變量對(duì)象,其中包含的是被拋出錯(cuò)誤對(duì)象的聲明

with語(yǔ)句,會(huì)將制定的對(duì)象添加到作用域鏈中

沒(méi)有塊級(jí)作用域

在其他類(lèi)C語(yǔ)言中,由花括號(hào)封閉的代碼都有自己的作用域,但JavaScript不會(huì)

if (true) {
    var color = "blue";
}
alert(color);        // "blue"

聲明變量,使用var聲明的變量會(huì)自動(dòng)被添加到最接近的環(huán)境中,在函數(shù)內(nèi)部,就是函數(shù)的局部環(huán)境

查詢(xún)標(biāo)識(shí)符,逐級(jí)向上查詢(xún),如果存在一個(gè)局部的變量定義,則搜索停止。如果局部環(huán)境中存在著同名的標(biāo)識(shí)符,就不會(huì)使用位于父環(huán)境中的標(biāo)識(shí)符

var color = "blue";
function getColor() {
    var color = "red";
    return color
}
alert(getColor());        // "red"
alert(color);             // "blue"

訪(fǎng)問(wèn)局部變量要比訪(fǎng)問(wèn)全局變量更快,因?yàn)椴挥孟蛏纤阉髯饔糜蜴?。不過(guò)JavaScript引擎在優(yōu)化標(biāo)識(shí)符查詢(xún)方面做的不錯(cuò),因此這個(gè)差別在將來(lái)恐怕就可以忽略不計(jì)了

垃圾收集

JavaScript具有自動(dòng)垃圾收集機(jī)制,即,執(zhí)行環(huán)境會(huì)負(fù)責(zé)管理代碼執(zhí)行過(guò)程中使用的內(nèi)存

這種機(jī)制很簡(jiǎn)單,找出那些不再繼續(xù)使用的變量,然后釋放其占用的內(nèi)存,為此垃圾收集器會(huì)按照固定的時(shí)間間隔(或代碼執(zhí)行中預(yù)定的收集時(shí)間),周期性的執(zhí)行這一操作

標(biāo)記清除(mark-and-sweep)

標(biāo)記清除是JavaScript中最常用的垃圾收集方式

當(dāng)變量進(jìn)入環(huán)境,就標(biāo)記“進(jìn)入環(huán)境”。從邏輯上講,永遠(yuǎn)不能釋放進(jìn)入環(huán)境的變量所占用的內(nèi)存。而當(dāng)變量離開(kāi)環(huán)境時(shí),則將其標(biāo)記為離開(kāi)環(huán)境

引用計(jì)數(shù) (reference counting)

當(dāng)聲明了一個(gè)變量并將一個(gè)引用類(lèi)型值賦給變量時(shí),則這個(gè)值的引用次數(shù)就+1

當(dāng)引用了這個(gè)值的變量又被賦給了其他值,則這個(gè)值的引用次數(shù)-1

當(dāng)這個(gè)值的次數(shù)變成0時(shí),就可以將其占用的內(nèi)存空間回收

當(dāng)兩個(gè)對(duì)象的屬性互相引用對(duì)方時(shí),陷入死循環(huán),將無(wú)法回收,為此Netscape在navigator 4.0中放棄了該方案

管理內(nèi)存

一旦數(shù)據(jù)不再有用,最好通過(guò)將其值設(shè)置為null來(lái)釋放引用——解除引用(dereferencing),這一做法適用于大多數(shù)全局變量和全局對(duì)象的屬性,而局部變量會(huì)自動(dòng)被解除引用

解除引用不會(huì)立即觸發(fā)回收機(jī)制,而是讓其脫離執(zhí)行環(huán)境,以便下一次回收時(shí)釋放內(nèi)存

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/104169.html

相關(guān)文章

  • JavaScript高級(jí)程序設(shè)計(jì)》(3讀書(shū)筆記 7 函數(shù)表達(dá)式

    摘要:定義函數(shù)表達(dá)式的方式有兩種函數(shù)聲明。不過(guò),這并不是匿名函數(shù)唯一的用途??梢允褂妹瘮?shù)表達(dá)式來(lái)達(dá)成相同的結(jié)果閉包匿名函數(shù)和閉包是兩個(gè)概念,容易混淆。匿名函數(shù)的執(zhí)行環(huán)境具有全局性,因此其對(duì)象通常指向通過(guò)改變函數(shù)的執(zhí)行環(huán)境的情況除外。 定義函數(shù)表達(dá)式的方式有兩種: 函數(shù)聲明。它的重要特征就是 函數(shù)聲明提升(function declaration hoisting) 即在執(zhí)行代碼之前會(huì)...

    鄒立鵬 評(píng)論0 收藏0
  • JavaScript高級(jí)程序設(shè)計(jì)》(3讀書(shū)筆記 1~2

    摘要:表示應(yīng)該立即下載腳本,但不應(yīng)妨礙頁(yè)面中的其他操作可選。表示通過(guò)屬性指定的代碼的字符集。表示腳本可以延遲到文檔完全被解析和顯示之后再執(zhí)行。實(shí)際上,服務(wù)器在傳送文件時(shí)使用的類(lèi)型通常是,但在中設(shè)置這個(gè)值卻可能導(dǎo)致腳本被忽略。 第1章 JavaScript 簡(jiǎn)介 雖然JavaScript和ECMAScript通常被人們用來(lái)表達(dá)相同的含義,但JavaScript的含義比ECMA-262要多得多...

    Corwien 評(píng)論0 收藏0
  • JavaScript語(yǔ)言精粹 修訂讀書(shū)筆記

    摘要:于是我就先把這本薄的經(jīng)典書(shū)語(yǔ)言精粹修訂版豆瓣讀書(shū)本書(shū)簡(jiǎn)介總共章,除去附錄,才頁(yè),讀完并記錄了一些筆記。讀書(shū)筆記還可以分享給別人看。編程語(yǔ)言第版定義了的標(biāo)準(zhǔn)。程序檢查時(shí)丟棄值為函數(shù)的屬性。 之前看到這篇文章,前端網(wǎng)老姚淺談:怎么學(xué)JavaScript?,說(shuō)到怎么學(xué)習(xí)JavaScript,那就是看書(shū)、分析源碼。10本書(shū)讀2遍的好處,應(yīng)該大于一本書(shū)讀20遍。看書(shū)主動(dòng)學(xué)習(xí),看視頻是被動(dòng)學(xué)習(xí)???..

    EscapedDog 評(píng)論0 收藏0
  • JS學(xué)習(xí)筆記4)(變量、作用域和內(nèi)存問(wèn)題

    摘要:具體來(lái)說(shuō)就是當(dāng)執(zhí)行流進(jìn)入下列任何一個(gè)語(yǔ)句時(shí),作用域鏈就會(huì)得到加長(zhǎng)語(yǔ)句的塊和語(yǔ)句。這兩個(gè)語(yǔ)句都會(huì)在作用域鏈的前端添加一個(gè)變量對(duì)象。對(duì)來(lái)說(shuō),會(huì)將指定的對(duì)象添加到作用域鏈中。 1. 基本類(lèi)型和引用類(lèi)型的值 JavaScript變量可以用來(lái)保存兩種類(lèi)型的值:基本類(lèi)性值和引用類(lèi)性值?;绢?lèi)型值源自以下5種基本數(shù)據(jù)類(lèi)型:Undefined、Null、Boolean、Number和String?;?..

    linkin 評(píng)論0 收藏0
  • JavaScript高級(jí)程序設(shè)計(jì)》(3讀書(shū)筆記 5 引用類(lèi)型

    摘要:引用類(lèi)型的值對(duì)象是引用類(lèi)型的一個(gè)實(shí)例。引用類(lèi)型是一種數(shù)據(jù)結(jié)構(gòu),用于將數(shù)據(jù)和功能組織在一起。對(duì)數(shù)組中的每一項(xiàng)運(yùn)行給定函數(shù),如果該函數(shù)對(duì)任一項(xiàng)返回,則返回。組零始終代表整個(gè)表達(dá)式。所以,使用非捕獲組較使用捕獲組更節(jié)省內(nèi)存。 引用類(lèi)型的值(對(duì)象)是引用類(lèi)型的一個(gè)實(shí)例。 引用類(lèi)型是一種數(shù)據(jù)結(jié)構(gòu),用于將數(shù)據(jù)和功能組織在一起。它同行被稱(chēng)為類(lèi),但這種稱(chēng)呼并不妥當(dāng),盡管ECMAScript從技術(shù)上講...

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

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

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<