#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]