深浅拷贝

230 阅读2分钟
原始类型存储的都是值
boolean
null
undefined
number
string
symbol

对象类型存储的是地址(指针)

将变量赋值给另外一个变量时,复制的是原本变量的地址(指针),也就导致了两个变量的值都发生了改变。

typeof 对于原始类型来说,除了 null 都可以显示正确的类型
typeof 对于对象来说,除了函数都会显示 object

判断一个对象的正确类型,这时候可以考虑使用 instanceof,因为内部机制是通过原型链来判断的
instanceof 判断类型也不是完全准确的。

延申:
number问题:0.1+0.2!=0.3
0.1二进制表示:末尾是0011循环,裁剪后,末尾只剩002
JS 采用的浮点数标准却会裁剪掉二进制里循环的数字,出现精度丢失
解决:
parseFloat((0.1 + 0.2).toFixed(10)) === 0.3 // true
把 Number 四舍五入为指定小数位数的数字

[1,2,3,4,5,5].splice(1,2,4)
(2) [2, 3]
let c=[1,2,3,4,5,5]
undefined
c.splice(1,2,4)//splice(删除起始位置,删除多少项,插入哪些项)
(2) [2, 3]
c 
(5) [1, 4, 4, 5, 5]



接口数据去重:
let result= [
  {id:'2323'}, {id:'23233'}, {id:'2323'}
]
//forEach splice
let resultClone=[]
result.forEach(item=> {
  let index=resultClone.indexOf(item.id)
  if(index ===-1){
    resultClone.push(item.id)
  } 
})

浅拷贝 
实现方式一:
let a=[1,2,3,4]
let b=[...a]
a.splice(0,1)
b
(4) [1, 2, 3, 4]
a
(3) [2, 3, 4] 
b
(4) [1, 2, 3, 4] 

 
对象扩展运算符...可以实现第一层级的拷贝(此处指:只拷贝值,不拷贝地址指针)
let aa={
    name:'dfd',
    person:{
      age:23
    }
  }
undefined
let bb={...aa}
undefined
aa.name='qgz'//可以实现第一层级的拷贝
"qgz"
bb
{name: "dfd", person: {…}}


let a=[
  {
    name:'dfd',
    person:{
      age:23
    }
  }
]
let b=[...a] 
a[0]={} 
b 
0: {name: "qgz", person: {…}}
length: 1
__proto__: Array(0)
a[0].name='qgz' //此处修改的是第二层,所以:
b
[{…}]0: {name: "qgz", person: {…}}length: 1__proto__: Array(0)

...底层实现:
class Student{
        constructor(name, age) {
            this.name=name;
            this.age=age;
        }
    }
 
Student.prototype.Objectvalues = function () {
    var buffer = [];
    console.log(this)//Student{name: "小刚", age: 18}
    for(key in this) { 
        buffer.push(this[key]);
    }
    return buffer;
}
    var stu = new Student("小刚",18);
 
    let keys = stu.Objectvalues(); 
keys 
let aa=Object.values(stu) 
aa
(2) ["小刚", 18]

进入正题:
深拷贝:
function deepClone(obj) { 
  function isObject(o){
    return(typeof o ==='object' || typeof o ==='function')&& o!=null
  }
    if(!isObject(obj)){
      throw new Error('非对象')
    }
    //...浅拷贝第一层,如果直接: let cloneValue =obj 导致所有层级都拷贝地址指针
    let cloneValue = Array.isArray(obj)?[...obj]:{...obj}
    //静态方法 Reflect.ownKeys() 返回一个由目标对象自身的属性键组成的数组。
    Object.keys(obj).forEach(function (key) {
      cloneValue[key]=isObject(obj[key])?deepClone(obj[key]):obj[key]
    }) 
  return cloneValue
}