国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

js中的值類型、引用類型、堆、棧、函數參數傳遞方式、連續賦值等概念的學習

hizengzeng / 1863人閱讀

摘要:值類型基本類型和棧內存值類型也稱為原始數據或原始值這類值存儲在棧內存中基本類型的值不可以修改。目前中的基本類型一共有六種。堆的使用規則當創建數組時,就會在堆內存中創建一個數組對象,并且在棧內存中創建一個對數組的引用。

值類型(基本類型)和棧內存

值類型也稱為原始數據或原始值(primitive value).這類值存儲在棧(stack)內存中, 基本類型的值不可以修改。每當我們定義一個變量,并賦給它一個基本類型的值時,可以理解為,我們為這個變量綁定了一個內存空間,這個內存空間存放的就是變量的值。因此?;绢愋蛿祿谴娣旁跅却嬷械暮唵螖祿?,數據大小確定,內存空間大小可以分配。
目前js中的基本類型一共有六種:null,undefined,boolean,number,,string,symbol。其中symbol是es6中新加的數據類型。這些類型在內存中分別占用固定大小的空間,他們的值保存在??臻g,我們通過按值來訪問的、
讓我們看一個基本類型的值不可以修改的示例

var a = 4;
a = 3; //注意,這里是覆蓋,不是修改

var num1 = 5;
var num2 = num1;

num1+=1;
consol.log(num1);//6
console.log(num2);//5

從上面第二個例子可以看到,從一個變量向另一個變量復制基本類型的值,我們會在變量對象上重新創建一個新值,然后把值復制到新變量分配的位置上,這兩個值是完全獨立的,對著兩個變量進行操作是互不影響的。

引用類型

這類值存儲在堆內存中,堆是內存中的動態區域,相當于自留空間,在程序運行期間會動態分配給代碼和堆棧。對中存儲的一般都是對象,然后在棧內存中存儲一個變量指針,計算機通過這個變量指針,找到堆中的數據塊并進行操作。這種訪問方式,我們叫它按引用訪問。如圖所示。

堆的使用規則
var fruit_1 = "apple";
var fruit_2 = "orange";
var fruit_3 = "banana";
var oArray = [fruit_1,fruit_2,fruit_3];
var newArray = oAarray;

當創建數組時,就會在堆內存中創建一個數組對象,并且在棧內存中創建一個對數組的引用。變量fruit_1、fruit_2、fruit_3為基本數據類型,他們的值直接存放在棧中;newArray、oArray為符合數據類型(引用類型),他們的引用變量存放在棧中,指向于存放在堆中的實際對象。
此時我們改變oAarray中的值,對應的newArray也會改變,因為它們的存儲的指針指向同一個堆地址。

console.log(oArray[1]);// 返回 orange
newArray[1]="berry";
console.log(oArray[1]);// 返回 berry

例如,下面代碼將newArray賦值為null:

newArray = null;

注意:接觸一個值的引用并不意味著自動回收改值所占用的內存。解除引用的真正作用時讓值脫離執行環境,以便垃圾收集器下次運行時將其回收。

為什么會有棧內存和堆內存之分?

與垃圾回收機制有關,為了使程序運行時占用的內存最小。
當一個方法執行時,每個方法都會建立自己的內存棧,在這個方法內定義的變量會逐個放入這塊棧內存里,隨著方法的執行結束,這個方法的內存棧也將自然銷毀了。因此,所有在方法中定義的變量都是放在棧內存中的;
當我們在程序中創建一個對象時,這個對象將被保存到運行時數據區中,以便反復理由(因為對象的創建成本通常比較大),這個運行時數據區就是堆內存。堆內存中的對象不會隨方法的結束而銷毀,即使方法結束后,這個對象還可能被另一個引用變量所引用(方法的參數傳遞時很常見),則這個對象依然不會被銷毀,只有當一個對象沒有任何引用變量引用它時,系統的垃圾回收機制才會在核實的時候回收它。

函數中參數傳遞方式,按值傳遞和按引用傳遞

按值傳遞:函數的形參時被調用時所傳實參的副本,修改形參并不會影響實參。

var num = 10;
function change(num){
    num = num * 10;
}
change(num)
console.log(num);       // 2

可以看到這里的變量num在運行完函數以后,值并沒有發生改變。

按引用傳遞:函數的形參接收實參的內存地址,而不再是副本。這意味著函數形參的值如果被修改,實參也會被修改。

var ab={
    x:1,
    y:2
}

function foo(obj){
    obj.x = 2
}
foo(ab)

console.log(ab);    //{x:2,y:2}

可以看到,原來的ab對象,在函數foo調用之后,其中的對象屬性發生變化。由上面的兩個例子,我們是不是可以推斷在js中,對于基本類型的數據,在函數傳遞過程中使用的時按值傳遞,而對于引用類型數據,在函數傳遞過程中使用的時是按引用傳遞方式呢?讓我們再看另外一個例子。

var ab={
    x:1,
    y:2
}

function foo(obj){
    obj = {
        x:2,
        y:3
    }
}
foo(ab)

console.log(ab);    //{x:1,y:2}

這個示例,如果按照我們剛剛說的結論,這里的函數運行后,輸出的對象ab的值應該是{x:2,y:3}。但是真正的結果確實{x:1,y:2}。這就奇怪了,到底js中的函數參數的傳遞方式是按什么樣的方式呢。我在網上找了很多資料,發現有個說法叫按共享傳遞。簡單來說,就是對于基本類型,是按值傳遞,對于對象而言,直接修改形參對實參沒有效果,而修改形參的屬性卻可以同時修改實參的屬性。而我的理解是這樣的??匆粡垐D。

由我們上面對引用類型與堆內存的介紹,我們知道,當我們定義一個ab對象時,系統會在堆中開出一個空間用來存儲改對象,對應的在棧內存中開出一個空間,用來存儲指向對象的地址。如上圖,根據按引用傳遞的方式,我們知道,foo函數內部的obj。在函數編譯的時候,是指向ab所指向的對象的,二者共用一個地址。當函數執行后,obj指向了新的對象地址,但是之前的ab所指向的對象屬性,依舊被ab所引用,沒有任何改變。所以,這里輸出的ab的值依舊未變。
而對于函數內部,改變形參的屬性值這個情況,我們也可以很容易的清楚,因為函數內部的obj和ab對象共同指向同一個對象空間,所以改變前者的對象屬性的值,自然會影響后者

一道經典的面試題
var a = {n:1};
var b = a;

a.x = a = {n:2};
console.log(a.x);
console.log(b.x)

這道題考察了很多東西,js中的運算符的優先級,比如賦值運算,是從右到左的。js中的對象存儲的問題。但是這道題很容易根據賦值運算是從右到左的順序運行的來得到錯誤的結果

a = {n:2}
a.x = a

然后得到了錯誤的答案。a.x = {n:2}.實際上,要解出這道題,我們至少要知道兩個,第一個就是運算符的優先級問題,點運算符的優先級高于賦值運算級。所以這里的執行順序第一步肯定是a.x,然后才是從右到左的賦值運算;第二個,我們要知道的是,js對象在內存中是如何存儲的。知道這兩點,那這道題就不難解決了。同樣的,我們繼續看幾張圖。
。
通過該題的前兩行代碼的聲明a和b,結合上面所說的對象存儲的原理,可以很容易看明白。a和b指向同一個對象空間。

a.x = a = {n:2}

這行代碼,首先會運行a.x。這樣便會在{n:1}對象所存儲的空間上添加一個x屬性名,并且等待賦值。即原來的{n:1}變成{n:1,x:undefined}。然后,按照賦值運算的順序,先將變量a的指向變為{n:2},但是這里要注意,{n:1,x:undefined}由于被b引用,所以依舊存在在內存當中。然后執行 ax.x = a,這里要注意,這里的a已經是{n:2}了。而a.x則是b指向的{n:1,x:undefined}中的x屬性,所以最終b指向的{n:1,x:undefined}變為{n:1,x:{n:2}}。
所以最后的結果??聪聢D。

console.log(a.x);   //undefined
console.log(b.x);   //{n:2}


參考鏈接:
https://www.imooc.com/article...
https://blog.csdn.net/lxiang2...
https://blog.csdn.net/xdd1991...
https://segmentfault.com/a/11...
https://blog.csdn.net/u012860...

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/97561.html

相關文章

  • 第二章 一切都是對象

    摘要:此內存區域的唯一目的就是存放對象實例,幾乎所有的對象實例都在這里分配內存。不過,無論如何劃分,都與存放內容無關,無論哪個區域,存儲的都仍然是對象實例,進一步劃分的目的是為了更好地回收內存,或者更快地分配內存。 一、對象和類的存儲 根據java虛擬機規范第七版的規定,Java虛擬機所管理的內存將包括以下幾個運行時數據區域:程序計數器、方法區、堆、虛擬機棧、本地方法棧。(詳見深入理解jav...

    孫吉亮 評論0 收藏0
  • 前端進擊巨人(二):、、隊列、內存空間

    摘要:中有三種數據結構棧堆隊列。前端進擊的巨人一執行上下文與執行棧,變量對象中解釋執行棧時,舉了一個乒乓球盒子的例子,來演示棧的存取方式,這里再舉個栗子搭積木。對于基本類型,棧中存儲的就是它自身的值,所以新內存空間存儲的也是一個值。 面試經常遇到的深淺拷貝,事件輪詢,函數調用棧,閉包等容易出錯的題目,究其原因,都是跟JavaScript基礎知識不牢固有關,下層地基沒打好,上層就是豆腐渣工程,...

    edgardeng 評論0 收藏0
  • ?搞不懂JS賦值·淺拷貝·深拷貝請看這里

    showImg(https://segmentfault.com/img/bVbvpCA); 前言 為什么寫拷貝這篇文章?同事有一天提到了拷貝,他說賦值就是一種淺拷貝方式,另一個同事說賦值和淺拷貝并不相同。我也有些疑惑,于是我去MDN搜一下拷貝相關內容,發現并沒有關于拷貝的實質概念,沒有辦法只能通過實踐了,同時去看一些前輩們的文章總結了這篇關于拷貝的內容,本文也屬于公眾號【程序員成長指北】學習路線...

    lauren_liuling 評論0 收藏0
  • JavaScript學習總結(一)基礎部分

    摘要:前綴規范每個局部變量都需要有一個類型前綴,按照類型可以分為表示字符串。例如,表示以上未涉及到的其他對象,例如,表示全局變量,例如,是一種區分大小寫的語言。布爾值與字符串相加將布爾值強制轉換為字符串。 基本概念 javascript是一門解釋型的語言,瀏覽器充當解釋器。js執行時,在同一個作用域內是先解釋再執行。解釋的時候會編譯function和var這兩個關鍵詞定義的變量,編譯完成后從...

    AlanKeene 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<