JavaScript数据类型及深拷贝与浅拷贝

JavaScript的数据类型分为基本类型引用类型

基本类型

基本类型包括undefined、null、string、number、boolean、(ES6中还有Symbol)

这些类型是存放在栈中的,数据大小确定,可按值访问,直接操作保存在变量中的实际值。

var a = 10;
var b = a;
b = 20;
console.log(a); // 10
console.log(b); // 20

复制时栈内存会开辟一个新内存来存放。按值传递,改变其中一个不会改变另一个,互相独立。

引用类型

引用类型就是Object(包括Array、RegExp、Date、function)

引用类型是存放在堆内存中的对象。
变量是保存在栈内存中的一个指针,这个指针保存的是堆内存中的引用地址,指向堆内存中的对象。

var obj1 = new Object();
var obj2 = obj1;
obj2.name = "名字";
console.log(obj1.name);  //名字

按址传递,=只是将这个堆内存对象在栈内存中的地址复制了一份给obj2,但是它们指向了同一个堆内存对象,修改其中一个变量就是在修改另一个。

判断数据类型的方法

typeof
typeof可以得到以下几种类型:
number、string、boolean、object、function、undefined、symbol

typeof ''; // string 有效
typeof 1; // number 有效
typeof Symbol(); // symbol 有效
typeof true; //boolean 有效
typeof undefined; //undefined 有效
typeof null; //object 无效
typeof [] ; //object 无效
typeof new Function(); // function 有效
typeof new Date(); //object 无效
typeof new RegExp(); //object 无效

需要注意的是

typeof null; //object

而且除了function外无法具体区分其他的object

instanceof
用来判断A是否是B的实例,返回的是一个布尔值。

console.log([] instanceof Array);  //true
console.log([] instanceof Object);  //true
console.log(/^$/ instanceof RegExp);  //true

需要注意的是
这种方式判断一个数组是否为数组或对象的结果都为true,所以可以用Array.isArray()来判断Array类型。
这种方式不可以用来检测基本类型

console.log(1 instanceof Number);  //false

constructor
对象的constructor是指向其构造函数的。

console.log([].constructor === Array);  //true
console.log([].constructor === Object);  //false
console.log({}.constructor === Object);  //true
console.log([].constructor === Object);  //false
console.log(1.constructor === Number);  //true

需要注意的是
null和undefined是没有constructor的,不能用这种方式判断。

toString()
这种方法是最万能的。
toString()是Object的原型方法,会返回当前对象的数据类型。通过call()使这个方法中的this指向需要检测的值。返回的格式为[object XX]

Object.prototype.toString.call('') ;   // [object String]
Object.prototype.toString.call(1) ;    // [object Number]
Object.prototype.toString.call(true) ; // [object Boolean]
Object.prototype.toString.call(Symbol()); //[object Symbol]
Object.prototype.toString.call(undefined) ; // [object Undefined]
Object.prototype.toString.call(null) ; // [object Null]
Object.prototype.toString.call(new Function()) ; // [object Function]
Object.prototype.toString.call(new Date()) ; // [object Date]
Object.prototype.toString.call([]) ; // [object Array]
Object.prototype.toString.call(new RegExp()) ; // [object RegExp]
Object.prototype.toString.call(new Error()) ; // [object Error]
Object.prototype.toString.call(document) ; // [object HTMLDocument]
Object.prototype.toString.call(window) ; //[object global] window 是全局对象 global 的引用

需要注意的是
toString()方法在每种类原型中都有,但是除了Object的原型,其他的都是把数据转换为字符串的意思。

浅拷贝

浅拷贝就是只复制指向某个对象的指针,而不复制对象本身,新旧对象共享同一块内存。

浅拷贝的实现方法

直接赋值

 let a = 1;
 let b = a;
 b = 2;
 console.log(a);  //2
 console.log(b);  //2

Object.assign()

 let obj = {name:'Carol', age:{child:12}}
 let copy = Object.assign({},obj);
 copy.name = 'Lee';
 copy.age.child = 24;
 console.log(obj);// {name:'Lee',age:{child:24}}

函数实现

 function shallowClone (source){
     if(!source || typeof source != 'object'){
         throw new Error ('error');
     }
     var targetObj = source.constructor === Array ? [] : {};
     for(var keys in source) {
         if(source.hasOwnProperty(keys)){
             targetObj[keys] = source[keys];
         }
     }
     return targetObj;
 }

深拷贝

复制并创建一个一模一样的对象,不共享内存,修改新对象,旧对象保持不变。

深拷贝的实现方式

函数实现

//使用循环遍历的方式实现数组、对象的深拷贝

function deepClone(obj) {
  //判断拷贝的要进行深拷贝的是数组还是对象,是数组的话进行数组拷贝,对象的话进行对象拷贝
  var objClone = Array.isArray(obj) ? [] : {};
  //进行深拷贝的不能为空,并且是对象
  if (obj && typeof obj === "object") {
    for (key in obj) {
      if (obj.hasOwnProperty(key)) {
        if (obj[key] && typeof obj[key] === "object") {
          objClone[key] = deepClone1(obj[key]);
        } else {
          objClone[key] = obj[key];
        }
      }
    }
  }
  return objClone;
}

借用JSON的parse()和stringify()方法

   //借用JSON对象的stringify把对象转为字符串,然后用parse转成新的对象
   
    function deepClone(obj){
        let _obj = JSON.stringify(obj),
        let objClone = JSON.parse(_obj);
        return objClone;
    }    
    let a=[0,1,[2,3],4],
    let b=deepClone(a);
    a[0]=1;
    a[2][0]=1;
    console.log(a,b);

图解

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/lixinyi0622/article/details/84594661