JS类型判断与深浅拷贝

类型判断

JS数据类型
  • 基本数据类型:String、Number、Boolean、Symbol、Null、Undefined
  • 引用数据类型:Object
数据类型的判断
  1. typeof
typeof 'aa'          // "string"
typeof 1;			 // "number" 
typeof true;	     // "boolean" 
typeof Symbol();	 // "symbol" 
typeof [];	         // "object" 
typeof {};	         // "object" 
typeof undefined; ;	  // "undefined" 
typeof null;     	 // "object"
typeof new Date();    // "object" 
typeof new Function();    // "object" 
typeof new RegExp();    // "object" 

可以看到typeof无法明确区分出Array、null、Object、Date、Reg

  1. instanceof
    用来判断已知是对象的target的具体类型,判断A是否是B的实例,检测的是原型
[] instanceof Array  // true
Symbol() instanceof Symbol  // true
{} instanceof Object  // true
new Date() instanceof Date  // true
new RegExp() instanceof RegExp  // true
new Function() instanceof Function  // true
  1. constructor
[].constructor ===  Array  // true
Symbol().constructor ===  Symbol  // true
{} instanceof Object  // true
new Date().constructor ===  Date  // true
new RegExp().constructor ===  RegExp  // true
new Function().constructor ===  Function  // true
  1. prototype
    Object.prototype.toString.call(target) === ‘[object Type]’
Object.prototype.toString.call(1) ===  '[object Number]'
Object.prototype.toString.call('') ===  '[object String]'
Object.prototype.toString.call(true) ===  '[object Boolean]'
Object.prototype.toString.call(null) ===  '[object Null]'
Object.prototype.toString.call(undefined) ===  '[object Undefined]'
Object.prototype.toString.call([]) ===  '[object Array]'
Object.prototype.toString.call(new Date) ===  '[object Date]'
Object.prototype.toString.call(function a(){}) ===  '[object Function]'

判断数组的方法

function adjustArray(o) {
    if(!o) {
        return false;
    }
    if(typeof Array.isArray === 'function') {
        return Array.isArray(o);
    } else {
        return Object.prototype.toString.call(o) === '[object Array]';
    }
}


深浅拷贝

浅拷贝

浅拷贝的意思就是只复制引用(指针),而未复制真正的值。用=复制

深拷贝
  • 方法一
// 递归
export function deepCopy(target) {
    if(!target || typeOf target != 'object') {
        return target;
    }
    let newObj = target.constructor == Array ? [] : {};
    for (let i in target) {
        if(target.hasOwnProperty(i)){
            if(target[i] && typeof target[i] == 'object'){
                newObj[i] = deepCopy(target[i]);
            } else {
                newObj[i] = target[i];
            } 
        }
    }
    return newObj;
}

  • 方法二
// JSON 简单情形(undefined、function、symbol 会在转换过程中被忽略)
let newObj = JSON.parse(JSON.stringfy(target));

首层浅拷贝

首层浅拷贝:对目标对象的第一层进行深拷贝,然后后面的是浅拷贝,可以称作“首层浅拷贝”。

  1. js数组有两个方法 concat 和 slice 是可以实现对原数组的拷贝的,这两个方法都不会修改原数组,而是返回一个修改后的新数组。他们实现的是首层浅拷贝
  2. Object.assign() 拷贝的是属性值。是首层浅拷贝。Object.assign(target, source) 方法只会拷贝源对象自身的并且可枚举的属性到目标对象。
  3. 拓展运算符(…)实现的同样是对对象进行首层浅拷贝
// 示例
const originArray = [1, 'aa',[ 'bb',2]];
const originObj = {a:1,b:{bb:2}};
 
const cloneArray = [...originArray];
cloneArray[0] = 0;
cloneArray[3].push(3);
console.log(originArray); // [1, 'aa',[ 'bb',2, 3]];
 
const cloneObj = {...originObj};
cloneObj.a = 2;
cloneObj.b.bb = 'rrr';
console.log(originObj); // {a:1,b:{bb:'rrr'}}

首层浅拷贝的实现
对对象第一层进行遍历赋值

function complexClone(source) {
  const targetObj = source.constructor === Array ? [] : {}; 
  for (let key in source) { // 遍历目标
    if (source.hasOwnProperty(key)) {
      targetObj[key] = source[key];
    }
  }
  return targetObj;
}

let temp = [1,2,3, [4,5]];
let cloneArr = complexClone(temp);
cloneArr[3][0] = 'aaaaa';
console.log(temp) // [1,2,3, ['aaaaa',5]];

总结:
赋值运算符 = 实现的是浅拷贝,只拷贝对象的引用值;
JavaScript 中数组和对象自带的拷贝方法都是“首层浅拷贝”;
JSON.stringify 实现的是深拷贝,但是对目标对象有要求(非 undefined,function);
若想真正意义上的深拷贝,请递归。



深度优先、广度优先遍历

和树的遍历类似,

  • 深度优先遍历(DFS):优先发现子节点,子节点遍历完成后再遍历兄弟节点;
  • 广度优先遍历:优先遍历同级兄弟节点,记录所有兄弟节点之后,再回头遍历子节点。

Advanced-Frontend中有两篇答题内容解释的很清楚,推荐大家看一下
深度优先、广度优先遍历概念
深度优先拷贝、广度优先拷贝实现

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值