摘要:接著下一個例子賦予副本新的地址可見,函數參數傳遞的并不是變量的引用,而是變量拷貝的副本,當變量是原始類型時,這個副本就是值本身,當變量是引用類型是,這個副本是指向堆內存的地址。
轉載自ConardLi: 《【JS進階】 你真的掌握變量和類型了嗎》 公眾號: code秘密花園
1. JavaScript數據類型ECMAScript標準規定了7種數據類型,這些數據類型分為原始類型和對象類型
1.1 原始類型局有不可變性:
如下:
var str = "abc";
str.slice(1);
str.substr(1);
str.trim(1);
str.toLowerCase(1);
str[0] = 1;
console.log(str); //abc
以上這些方法都在原字符串的基礎上產生一個新字符串,而非直接去改變str,這印證了字符串的不可變形。
當執行以下代碼時:
str += "6";
console.log(str); //abc6
可見str的值被改變了,這貌似與字符串的不可變性不符合呀,這個要從內存上來理解。
在JavaScript中,每一個變量在內存中都需要一個空間來存儲。
內存空間有分為棧內存和堆內存。
棧內存:
存儲的值大小固定
空間較小
可以直接操作其保存的變量,運行效率高
由系統自動分配存儲空間
JavaScript中的原始類型的值被直接存儲在占中,在變量定義時,棧就為其分配好了內存空間。
由于棧中的內存空間的大小是固定的,所以存儲在棧中的變量就是不可變的。
而當執行了 str += "6" 的操作時,實際上是在棧中又開辟了一塊內存空間用于存儲‘abc6’,然后將變量str指向這塊空間。
1.2 引用類型
堆內存:
存儲的值大小不定,可動態調整
空間較大,運行效率低
無法直接操作其內部存儲,使用引用地址讀取
通過代碼進行分配空間
引用類型的值實際存儲在堆內存中,它在棧中只存儲了一個固定長度的地址,這個地址指向堆內存中的值。
如下:
var obj1 = {name: "abc"};
var obj2 = {age: 18};
var obj3 = function() {...};
var obj4 = [1, 2, 3, 4, 5];
引用類型不具有不可變性,可以改變它們:
obj1.name = "abc6";
obj2.age = 19;
obj4.length = 0;
console.log(obj1); //{name: "abc6"}
console.log(obj2); //{age: 19}
console.log(obj4); //[]
以數組為例,它的很多方法都可以改變它自身:
pop()
push()
shift()
unshift()
reverse()
sort()
splice()
1.3 復制
原始類型的復制:
var name = "abc";
var name2 = name;
name2 = "code";
console.log(name); //abc
內存中有一個變量name,值為abc。從變量name復制出一個變量name2,此時在內存中創建了一個塊新的空間用于存儲abc,雖然兩者的值是相同的,但是兩者指向的內存空間完全不同,這兩個變量參與任何操作都互不影響。
引用類型的復制:
var obj = {name: "abc"};
var obj2 = obj;
obj2.name = "code";
console.log(obj.name); //code
當復制引用類型的變量時,實際上復制的是堆中存儲的地址,所以復制出來的obj2實際上和obj指向的堆中同一個對象。因此,改變其中任何一個變量的值,兩一個變量都會受到影響。
1.4 比較
當對兩個變量進行比較時,不同類型的變量的表現是不同的:
var name = "abc";
var name2 = "abc";
console.log(name === name2); //true
var obj = {name: "abc"};
var obj2 = {name: "abc"};
console.log(obj === obj2); //false
對于原始類型,比較時會直接比較它們的值,如果值相等,即返回true。
對于引用類型,比較時會比較它們的引用地址,雖然兩個變量在堆中存儲的對象具有屬性值都是相等的,但是它們被存儲在了不同的存儲空間,因此比較值為false。
1.5 值傳遞和引用傳遞
如下:
let name = "abc";
function changeValue(name) {
name = "code";
}
changeValue(name);
console.log(name);
執行上面的代碼,如果最終打印出來的name是‘abc’,沒有改變,說明函數參數傳遞的是變量的值,即值傳遞。如果最終打印出來的是‘code’,函數內部的操作可以改變傳入的變量,那么說明函數參數傳遞的是引用,即引用傳遞。
上面的例子執行結果是‘abc’,即函數參數僅僅是被傳入變量復制給了的一個局部變量。改變這個局部變量不會對外部變量產生影響。
let obj = {name: "abc"};
function changeValue(obj) {
obj.name = "code";
}
changeValue(obj);
console.log(obj.name); //code
ECMAScript中的所有的函數的參數都是按值傳遞的。
當函數參數是引用類型時,同樣將參數復制了一個副本到局部變量,只不過復制的這個副本是指向堆內存中的地址而已,在函數內部對對象的屬性進行操作,實際上和外部變量指向堆內存中的值相同,但是這并不代表這引用傳遞。
接著下一個例子:
let obj = {};
function changeValue(obj) {
obj.name = "abc";
obj = {name: "code"}; //賦予副本新的地址
}
changeValue(obj);
console.log(obj.name); //abc
可見,函數參數傳遞的并不是變量的引用,而是變量拷貝的副本,當變量是原始類型時,這個副本就是值本身,當變量是引用類型是,這個副本是指向堆內存的地址。
重要的事情說三遍:
ECMAScript中的所有的函數的參數都是按值傳遞的。
ECMAScript中的所有的函數的參數都是按值傳遞的。
ECMAScript中的所有的函數的參數都是按值傳遞的。
轉載自ConardLi: 《【JS進階】 你真的掌握變量和類型了嗎》 公眾號: code秘密花園
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/104924.html
摘要:所以說在中,也并不是一切都是對象原始類型值不可變原始類型的變量的值是不可變的,只能給變量賦予新的值。可以理解基本類型的變量的值,就是字面上寫的數值。有四個變量圖調用是傳參,內層的會屏蔽外層的。圖內層的的值被改變成的值被改變為。 showImg(https://segmentfault.com/img/bVbldfK); 1. demo 如果你對下面的代碼沒有任何疑問就能自信的回答出輸出...
摘要:引子前不久我建立的技術群里一位問了一個這樣的問題,她貼出的代碼如下所示執行結果如下所示第一個第二個這是一個令人詫異的結果,為什么第一個彈出框顯示的是,而不是呢這種疑惑的原理我描述如下一個頁面里直接定義在標簽下的變量是全局變量即屬于對象的變量 1) 引子 前不久我建立的技術群里一位MM問了一個這樣的問題,她貼出的代碼如下所示: var a = 1; function hehe...
摘要:一棧數據結構與不同,中并沒有嚴格意義上區分棧內存與堆內存。引用數據類型的值是保存在堆內存中的對象。不允許直接訪問堆內存中的位置,因此我們不能直接操作對象的堆內存空間。為了更好的搞懂變量對象與堆內存,我們可以結合以下例子與圖解進行理解。 showImg(https://segmentfault.com/img/remote/1460000009784102?w=1240&h=683); ...
摘要:要為變量或者常量指定類型也很簡單,就是在變量常量名后面加個冒號,再指定類型即可,比如聲明函數是類型,即返回值是類型聲明參數是類型聲明是無返回值的聲明是這段代碼演示了對函數類型參數類型和變量類型地聲明。變量函數參數和返回值需要申明類型。 從 JavaScript 語法改寫為 TypeScript 語法,有兩個關鍵點,一點是類成員變量(Field)需要聲明,另一點是要為各種東西(變量、參數...
摘要:對象數組初始化表達式,闖關記之上文檔對象模型是針對和文檔的一個。闖關記之數組數組是值的有序集合。數組是動態的,根闖關記之語法的語法大量借鑒了及其他類語言如和的語法。 《JavaScript 闖關記》之 DOM(下) Element 類型 除了 Document 類型之外,Element 類型就要算是 Web 編程中最常用的類型了。Element 類型用于表現 XML 或 HTML 元素...
閱讀 3094·2021-08-03 14:05
閱讀 2140·2019-08-29 15:35
閱讀 678·2019-08-29 13:30
閱讀 3169·2019-08-29 13:20
閱讀 2531·2019-08-23 18:15
閱讀 1796·2019-08-23 14:57
閱讀 2213·2019-08-23 13:57
閱讀 1310·2019-08-23 12:10