JS基础 - 值类型和引用类型

前端开发·教程·资源 · 2022-05-17

一、JavaScript中值的两种类型

简单数据类型:又叫值类型,基本类型。变量中存储的是值本身。

// 值类型
let a = 100;
let b = a;
b = 200;
console.log(a) //100;

常见值类型包含:String(字符串)、Number(数值)、Boolean(布尔值)、Undefined、Symbol(表示独一无二的值)。

let a ; //const 定义必须有值,let不用
const b = 'string';
const c = 123;
const d = true;
const s = Symbol('s');//ES6 新增类型

复杂数据类型:又叫引用类型。变量中存储的仅仅是地址(引用)。

// 引用类型
let a = {time:100};
let b = a;
b.time = 200;
console.log(a) //200;

其中包含:Array(数组)、Object(对象)、Null、Function(函数)。

// 引用类型
const a = [1,2,3];
const b = {time:100};
// 特殊的引用类型,指针指向空地址
const n = null;
// 特殊的引用类型,不用于存储数据,没有拷贝、复制函数的说法
function fn(){}
Undefined和 Null的区别:

null 表示“没有对象”,即该处不应该有值。典型用法是:

  1. 作为函数的参数,表示该函数的参数不是对象。
  2. 作为对象原型链的重点。

undefined 表示 “缺少值”,就是此处应该有一个值,但是还没有定义。典型用法是:

  1. 变量被声明了,但没有赋值时,就等于undefined。
  2. 调用函数时,应该提供的参数没有提供,该参数等于undefined。
  3. 对象没有赋值的属性,该属性的值为undefined。
  4. 函数没有返回值时,默认返回undefined。

二、值类型和引用类型的区别

值类型引用类型
存储位置值类型的变量内部存储的是值本身(栈)引用类型的变量中存储的是指向对象的一个内存地址(堆)
复制方式值类型的变量直接赋值就是深拷贝引用类型的变量直接赋值实际上是传递引用,只是浅拷贝。
属性和方法值类型无法添加属性和方法引用类型可以添加属性和方法
比较方式值类型的比较是值的比较,只有当它们的值相等的时候它们才相等引用类型的比较是引用地址的比较
堆栈空间分配区别:

栈(操作系统):由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。栈空间的特点是先进后出,后进先出,由上往下排列
堆(操作系统): 存储复杂类型(对象),一般由程序员分配释放, 若程序员不释放,由垃圾回收机制回收。由下往上排列

JavaScript中并没有严格意义上区分栈内存与堆内存。执行上下文的执行顺序借用了栈数据结构的存取方式。
== 和 ===区别:

相等(==),只判断值大小是否相等,不判断数据类型。
全等(=== ),不光判断值相等,还要判断数据类型相等

深拷贝和浅拷贝:

浅拷贝:复制对象的属性值时,只复制第一层的属性值。如果遇到对象类的属性值,不会深入复制,即如果是复制类型的数据,只复制了地址。
深拷贝:复制对象的属性值时,如果遇到对象类的属性值,进行深入复制,不仅仅是复制地址。

为什么要区分值类型和引用类型?

两者的存储速度不同,同时基于内存空间和CPU耗时来做区分。

三、typeof 运算符

  • 能识别所有的值类型

    let a ;                  typeof(a) //'undefined'
    const b = 'string';        typeof(b) //'string'
    const c = 123;            typeof(c) //'number'
    const d = true;            typeof(d) //'boolean'
    const s = Symbol('s');    typeof(s) //'symbol'
  • 能识别函数

    typeof( console.log) //'function'
    typeof( function fn(){}) //'function'
  • 能判断是否引用类型(无法再细分)

    const a = [1,2,3];     typeof(a) //'object'
    const b = {time:100};  typeof(b) //'object'
    const n = null;        typeof(n) //'object'
  • typeof 始终会返回字符串

请注意:

1、NaN 的数据类型是数值

2、数组的数据类型是对象

3、日期的数据类型是对象

4、null 的数据类型是对象

5、未定义变量的数据类型是 undefined

四、手写深拷贝

function deepClone(obj = {}) {
    //判断是否引用地址,不是则返回
    if (typeof obj != 'object' || typeof obj == null) return obj;
    let result
    if (obj instanceof Array) {
        result = []
    } else {
        result = {};
    }
    for (let k in obj) {
        //必须是自身的属性
        if (obj.hasOwnProperty(k)) result[k] = deepClone(obj[k]) //使用递归调用
    }
    return result;
}

let obj1 = {
    name: "hxf",
    city: { code: "cd", name: "成都市" },
    arr: [1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10]
};

let obj2 = deepClone(obj1);
obj2.city.code = 'sccd';
obj2.name = 'gonwe';
console.log(obj1);
console.log(obj2);
Javascript笔记 堆栈 深拷贝
Theme Jasmine by Kent Liao