JavaScript引用数据类型
引用数据类型与基本数据类型不同,它们在内存中的存储方式更为复杂。在栈中存放的是数据的地址,而具体的值则存储在堆中。JavaScript中引用数据类型主要就是对象(Object) ,所有引用类型的原型链最终都指向 Object.prototype
一、引用数据类型的特点
-
存放位置
基本数据类型值在内存中占据固定大小,直接存储在栈内存中,而引用数据类型的数据存储在堆内存中,其变量绑定存储的是对堆内存位置的引用。而这个地址存放在栈内存中。
不是所有引用都存储在栈内存:
- 只有当前执行上下文中的局部变量的引用会存储在栈内存
- 闭包变量、全局变量的引用实际存储在堆内存中的变量环境中
这是由于堆内存适合存储大小不固定、可能动态增长的数据结构,引用数据类型符合这一特征
-
值可变性
引用数据类型的值是可以修改的(与基本数据类型的不可变性相对),而基本数据类型修改值时实际上是创建了一个新值并赋给变量。
由于变量存储的是引用(内存地址),所以在修改数据时不会影响引用。并且引用可以存放相同地址,所以多个变量可以共享同一个对象。
// 可变 const obj = { name: '张三', age: 18 } obj.name = '李四' console.log(obj.name) // 李四 // 多个变量可以共享同一个对象 const pers = obj // 浅拷贝 拷贝的是对象的地址 pers.age = 30 console.log(obj.age) // 30引用共享带来的问题
多个变量共享同一个对象容易造成对象被意外修改的问题,在不改变原对象的基础上修改对象属性可以通拷贝来实现。
拓展运算符浅拷贝
{ ...obj }表示创建一个新对象,并将obj的所有可枚举属性展开到新对象中const person = { name: '张三', age: 18, sex: '男', friends: ['李四', '王五', '赵六'] } const cp = {...person} // 浅拷贝 cp.name = 'LiSi' console.log(person.name) // 张三 console.log(cp.name) // LiSi -
引用数据类型之间的比较
基本数据类型之间是值的比较,而引用数据类型之间是比较的是引用比较(地址比较)。看其的引用是否指向同一个对象
let a = 0 let b = 0 console.log(a === b) // true const arr1 = [1,2,3] const arr2 = [1,2,3] console.log(arr1 === arr2) //falsearr1与arr2虽然是内容相同的数组,但是他们在内存中的地址是不同的,他们所指向的对象不相同
二、主要引用数据类型
-
对象 (Object)
最基本的引用类型,用于存储键值对集合。这里的值可以可以是任何类型的数据(基本数据类型和引用数据类型都行),但是键只能是字符串或
Symbol,其他类型自动转为字符串const obj = { name: "张三", age: 18, sex: "男", friends: ["", "", ""], 86 : "Do not", [1]: 'one', // 匿名函数 sayHi: function () { console.log("hi"); }, }; console.log([1].toString()) // 1 console.log(obj[1]) -
函数 (Function)
在
JavaScript中函数不仅是可执行的代码块,还可以作为值进行传递、赋值给变量,或者作为参数传递给其他函数。函数也是对象并且所有JavaScript 中的函数实际上都是Function对象的实例// 创建函数 function eat() {} // 函数表达式 将函数赋值给变量 也-可以省略函数名 const fn = function() {} // 箭头函数 const fn2 = () => {} console.log(fn instanceof Object) // true console.log(fn instanceof Function) // true -
数组 (Array)
JavaScript中的数组是一种有序的数据集合,它可以存储不同类型的数据,本质是对象。其大小是动态的,不像其他语言有固定的长度。可以通过索引来访问或修改数组元素,数组中含有多种可以对数组进行操作的方法
// 字面量创建数组 const arr = [1,'sy',{name:'kk',age:18}] // 构造方法创建数组 const numbers = new Array(1, 2, 3); // es6新增 Array.of(1, 2, 3); // [1, 2, 3] Array.from('hello'); // ['h', 'e', 'l', 'l', 'o']数组存储数据的方案:
-
存储相同数据类型
当存储 31 位有符号整数
(-2³⁰ 到 2³⁰-1)时,每个元素的大小相同,为4字节(4 * 8 = 32位)const arr = [15,68,3,1468,461,8] // 所有元素所占空间大小相同当存储双精度浮点数时,每个元素大小相同,为8 字节(64 位)
const arr = [1.1, 2.2, 3.3]; // 所有元素大小相同 -
存储不同数据类型
当存储不同数据类型时,数组中存储的不是元素的值,而是指向实际值的指针,这时候数组的每个元素大小相同(即指针大小,通常 4 或 8 字节),实际上所占用的堆内存大小是不一样的
const arr = [86,'name',{id:'lei'}]
-