值类型与引用类型

一. 值类型与引用类型

  1. 值类型: string,number,boolean,undefined。
  2. 引用类型:
  • 对象:typeof的值为object
  • 数组:typeof的值为object
  • function:特殊的引用类型,不会存储数据,typeof的值为function
  • null: typeof的值为object

注:

  1. 判断null可用==,其中undefined==nullnull==null都为true
  2. 区分对象和数组:
  • Array.isArray(arr),该方法会判断传入的参数的数据类型是否为数组,返回boolean
  • 通过原型对象来判断,arr.__proto__ === Array.prototypeObject.getPrototypeOf(arr) === Array.prototypearr instanceof Array

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

  • 值类型的数据是保存在栈中
  • 引用类型的数据保存在堆中,在堆中的地址保存在栈中,变量指向的是栈中的地址,所以通过=对引用类型进行的拷贝是浅拷贝
// 值类型
var m = 123;
var n = m;
n = 456;
console.log(n); // 456
console.log(m); // 123

// 引用类型
var a = {name: '小红'};
var b = a;
b.name = '小明';
console.log(b.name); // 小明
console.log(a.name); // 小明

三、 浅拷贝与深拷贝

  • 浅拷贝:拷贝之后,新对象改变属性的值,原对象也会进行相应的改变
  • 深拷贝:拷贝之后,新对象对属性的改变,不会影响到原对象
  1. 深拷贝的方法
// 方法一
// 通过JSON.stringify()方法将引用类型转换成json字符串,然后再通过JSON.parse()方法将json字符串转换成json对象
var a = {name: '小红'};
var b = JSON.parse(JSON.stringify(a));
b.name = '小明';
console.log(b.name); // 小明
console.log(a.name); // 小红

// 方法二
// 通过递归的方法进行拷贝
function deepCopy(obj) {
  // 如果参数不是对象或数组,则直接返回
  if(typeof obj !== 'object' || obj == null) {
    return obj;
  }
  var res;
  if(obj instanceof Array) {
    res = [];
  } else {
    res = {};
  }
  for(var key in obj) {
    res[key] = deepCopy(obj[key]);
  }
  return res;
}
var a = {name: '小红'};
var b = deepCopy(a);
b.name = '小明';
console.log(b.name); // 小明
console.log(a.name); // 小红

四、深度比较

因为对象或数组的变量指向的是地址,所以通过===进行比较,只要不是同一个对象或数组,则返回false

var a = {name: '小红'};
var b = {name: '小红'};
console.log(a === b); // false
  • 通过递归进行深度比较
// 判断是否为对象或数组
function isObject(obj) {
  return typeof obj === 'object' && obj !== null;
}
function isEqual(obj1, obj2) {
  // 如果有一个参数不是对象或数组,则直接通过===进行判断
  if(!isObject(obj1) || !isObject(obj2)) {
    return obj1 === obj2;
  }
  // 如果传入的是同一个对象或数组,则直接返回true
  if(obj1 === obj2) {
    return true
  }
  // 如果一个对象一个是数组,则返回false
  if(Array.isArray(obj1) !== Array.isArray(obj2)) {
    return false;
  }
  // 如果属性数量不同,则返回false
  var length1 = Object.keys(obj1).length;
  var length2 = Object.keys(obj2).length;
  if(length1 !== length2) {
    return false;
  }
  // 以obj1为基准进行递归判断
  for(var key in obj1) {
    if(!isEqual(obj1[key], obj2[key])) {
      return false;
    }
  }
  return true;
}
var a = {name: '小红'};
var b = {name: '小红'};
console.log(isEqual(a, b)); // true

你可能感兴趣的:(值类型与引用类型)