【基础巩固】js值类型和引用类型

示例

值类型

let a = 100;
let b = a;
a = 200;
console.log(b); // 100 (互不影响)

引用类型

let a = { age: 20 };
let b = a;
a.age= 21;
console.log(b.age); // 21 (b.age随a.age的改变而改变)

存储方式

值类型


js变量存储在栈中,至于怎么存储咱先不管(毕竟我也不懂),这是js引擎的事情。
如图所示,key为变量名,value为存储内容,值类型变量的值直接存储在value中,a的值改变后并不会影响b的值。

引用类型


在栈中,引用类型存储的是内存地址,同时内存地址指向堆中的值,
简单地讲:引用类型a -> 内存地址1 -> a的值,此时若执行let b = a;,则是把b的内存地址指向了a的内存地址,而这个内存地址指向同一个值,所以a的值改变的时候,b的值也随之改变。

图片来源:学习资料

为什么引用类型要搞个内存地址?
众所周知最常见的引用类型是对象和数组,数组长度和对象属性数量是没有限制的,甚至可以嵌套,如果像存储值类型那样存储引用类型(没有内存地址,直接存储在栈中),那计算机怕是要炸了。

常见值类型和引用类型

// 常见值类型
let a; // undefined
const n = 100; // Number
const s = '100'; // String
const b = true; // Boolean
const s = Symbol('s') // Symbol(es6)
// 常见引用类型
const obj = { value: 100 }; // Object
const arr = [ 1, 2, 3 ]; // Array
const n = null; // 特殊引用类型,指针指向空地址
function fn() {} // 特殊引用类型,但不用于存储数据,所以不考虑深拷贝浅拷贝的问题

深拷贝

  • JSON.parse(JSON.stringify(obj))
    最简单的方式,但会忽略undefined,function,RegExp

  • Object.assign()或解构赋值(const a = {...obj}, const b = [...arr])
    注意这里并不是深拷贝,只是当对象或数组只有一层没有嵌套的时候可以使用此方式来进行拷贝

const obj1 = { a: 1, b: 2, c: 3, d: 4}; // 可以使用
const obj2 = { a: 1, b: { c: 3 }, d: 4 }; // 不可使用
  • 递归
const deepCopy = obj => {
    let copy = Array.isArray(obj) === true ? [] : {}
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            if (typeof obj[key] === 'object') {
                copy[key] = deepCopy(obj[key])
            } else {
                copy[key] = obj[key]
            }
        }
    }
    return copy
}
posted @ 2019-11-19 11:59  打杂工程师  阅读(590)  评论(0编辑  收藏  举报