#ECMAscript原始值、引用值、類型轉換、淺拷貝、深拷貝
##原始值
存儲在棧(stack)中的簡單數據段,也就是說,它們的值直接存儲在變量訪問的位置
棧區(stack):系統自動分配的內存空間,有系統自動釋放。
##引用值
存儲在堆(heap)中的對象,也就是說,存儲在變量處的值是一個指針(point),指向存儲對象的內存處
堆區(heap):動態分配的內存空間,大小不確定,也不會自動釋放。
##類型轉換
-
轉爲字符串
Boolean、String、Number是僞對象,他們實際上具有屬性和方法。所以都有相應的toString()方法進行轉化
(1)Number 類型的 toString() 方法 默認模式 var num1 = 1; var num2 = 1.0; num1.toString(); //返回 "1" num2.toString(); //返回 "1" (2)Number 類型的 toString() 方法 基模式 var num = 10; num.toString(2); //返回 "1010" num.toString(8); //返回 "12" num.toString(16); //返回 "A"
-
轉換爲數字
parseInt、parseFloat針對字符串。parseInt() 方法首先查看位置 0 處的字符,判斷它是否是個有效數字;如果不是,該方法將返回 NaN,不再繼續執行其他操作。如果是有效數字,則一直重複執行下去,直到發現不是有效數字,將這個字符之前有效的字符串轉爲數字
(1)parseInt() 函數 將值轉換爲整型 var num = parseInt("12abc"); //返回 12 var num = parseInt("0xA"); //返回 10 var num = parseInt("23.9"); //返回 23 var num = parseInt("abc"); //返回 NaN (2) parseInt() 函數 也有基模式 var num = parseInt("AF", 16); //返回 175 var num = parseInt("10", 2); //返回 2 var num = parseInt("10", 8); //返回 8 var num = parseInt("10", 10); //返回 10 var num = parseInt("010"); //返回 8 var num = parseInt("010", 8); //返回 8 var num = parseInt("010", 10); //返回 10 (3)parseFloat() 函數 字符串必須以十進制形式表示浮點數 var num = parseFloat("12abc"); //返回 12 var num = parseFloat("0xA"); //返回 NaN var num = parseFloat("1.2"); //返回 1.2 var num = parseFloat("1.2.3"); //返回 1.2 var num = parseFloat("0102"); //返回 102 var num = parseFloat("abc"); //返回 NaN
-
強制類型轉換
Boolean(value) - 把給定的值轉換成 Boolean 型
Number(value) - 把給定的值轉換成數字(可以是整數或浮點數)
String(value) - 把給定的值轉換成字符串
(1)Boolean() 函數 至少有一個字符的字符串、非 0 數字或對象時,Boolean() 函數將返回 true,如果是空字符串、數字 0、undefined 或 null,它將返回 false var b1 = Boolean(""); //false - 空字符串 var b1 = Boolean("hello"); //true - 非空字符串 var b1 = Boolean(300); //true - 非零數字 var b1 = Boolean(null); //false - null var b1 = Boolean(0); //false - 零 var b1 = Boolean(new object()); //true - 對象 (2)Number() 函數 與 parseInt() 和 parseFloat() 方法的處理方式相似,只是它轉換的是整個值,而不是部分值 var n1 = Number(false) //返回 0 var n1 = Number(true) //返回 1 var n1 = Number(undefined) //返回 NaN var n1 = Number(null) //返回 0 var n1 = Number("1.2") //返回 1.2 var n1 = Number("12") //返回 12 var n1 = Number("1.2.3") //返回 NaN var n1 = Number(new object()) //返回 NaN var n1 = Number(50) //返回 50 (3)String() 函數 可把任何值轉換成字符串 和調用 toString() 方法的唯一不同之處在於,對 null 和 undefined 值強制類型轉換可以生成字符串而不引發錯誤 var s1 = String(null); //"null" var oNull = null; var s2 = oNull.toString(); //會引發錯誤
##淺拷貝和深拷貝
深拷貝與淺拷貝的概念只存在於引用數據類型
-
基本數據類型
目前基本數據類型有:Boolean、Null、Undefined、Number、String、Symbol
基本數據類型在賦值操作時是傳值。在賦值操作時,基本數據類型的賦值是在內存裏開闢了一段新的棧內存,然後再把值賦值到新開闢的棧內存中。
-
引用數據類型
引用數據類型有:Object、Array、Function、RegExp、Date 等
引用數據類型在賦值操作時是傳址。在賦值操作時,引用類型的賦值只是改變了指針的指向,在給變量賦值時,是把對象保存在棧內存中的地址賦值給變量,結果是兩個變量指向同個棧內存地址。
-
淺拷貝
對基本數據類型進行值傳遞,對引用數據類型進行引用傳遞般的拷貝,此爲淺拷貝。
(1)通過擴展運算符...實現淺拷貝 (2)通過Object.assign()實現淺拷貝(可以實現一維對象的深拷貝) var obj1 = {x: 1, y: 2}, obj2 = Object.assign({}, obj1); console.log(obj1) //{x: 1, y: 2} console.log(obj2) //{x: 1, y: 2} obj2.x = 2; //修改obj2.x console.log(obj1) //{x: 1, y: 2} console.log(obj2) //{x: 2, y: 2} var obj1 = { x: 1, y: { m: 1 } }; var obj2 = Object.assign({}, obj1); console.log(obj1) //{x: 1, y: {m: 1}} console.log(obj2) //{x: 1, y: {m: 1}} obj2.y.m = 2; //修改obj2.y.m console.log(obj1) //{x: 1, y: {m: 2}} console.log(obj2) //{x: 2, y: {m: 2}}
-
深拷貝
對基本數據類型進行值傳遞,對引用數據類型,創建一個新的對象,並複製其內容,此爲深拷貝。
(1)通過Lodash的cloneDeepAPI 實現深拷貝 let _ = require('lodash'); let obj1 = { a: 1, b: { c: 2 } }; let obj2 = _.cloneDeep(obj1); obj2.b.c = 6; console.log(obj1.b.c); // 2 console.log(obj2.b.c); // 6 (2)通過JSON.parse(JSON.stringify())進行深拷貝,但會忽略undefined、任意的函數、symbol 值 var obj1 = { x: 1, y: { m: 1 }, a:undefined, b:function(a,b){ return a+b }, c:Symbol("foo") }; var obj2 = JSON.parse(JSON.stringify(obj1)); console.log(obj1) //{x: 1, y: {m: 1}, a: undefined, b: ƒ, c: Symbol(foo)} console.log(obj2) //{x: 1, y: {m: 1}} obj2.y.m = 2; //修改obj2.y.m console.log(obj1) //{x: 1, y: {m: 1}, a: undefined, b: ƒ, c: Symbol(foo)} console.log(obj2) //{x: 2, y: {m: 2}} (3)只能實現一維對象的深拷貝: Object.assign(): 見3.(2) slice(): var arr1 = [1, 2], arr2 = arr1.slice(); console.log(arr1); //[1, 2] console.log(arr2); //[1, 2] arr2[0] = 3; //修改arr2 console.log(arr1); //[1, 2] console.log(arr2); //[3, 2]