序言

  最近遇到几个js引用数据类型造成的bug,今天结合bug详细分析一下,避免以后再犯,也希望能帮大家提个醒,强化js基本功。

目录

  1、浅拷贝、深拷贝,解决变量赋值相互影响问题

  2、判断2个数组、对象是否相等

现象一

var a=;
var b=a;
b=;
console.log(a) //
console.log(b) // var obj1 = {
  id: ,
  info: {
name: '张三'
  }
};
var obj2 = obj1;
obj2.id = ;
obj2.info.name = '李四'
console.log(obj1)   // {id:2, info:{name: '李四'}}
console.log(obj2)         // {id:2, info:{name: '李四'}}

  1. 现象分析: 

    数组、对象都是用用数据类型。直接 = 赋值,或者 浅拷贝,这些变量实质上共享一个存储空间的数据。当你修改其中一个对象变量时,
  另一个也会变。  2. 深浅拷贝
     浅拷贝: 简单说,就是新的变量与原变量公用一个指针,即公用同一份存储空间的数据。改变a,b也会变
   深拷贝: 简单说就是把数据全部拔下来,重新存一下。a,b之间没有任何牵连    浅析:
  1. 这涉及到计算机原理的一些东西。js基本数据类型存在 栈内存 中, 当 a=b ,相当于新开辟一个存储空间,所以互不影响。
  2. 引用数据类型,名 存在栈内存中,值存在堆内存中,栈内存会额外存一个指向堆内存的指针,其实就是 堆内存地址。
  3. 我们对象 a=b 时,仅仅将名,即 栈内存中的数据复制了出来,但是栈内存的地址并没有变,所以a,b值会保持一致,互相影响。 3. 几个实现对象拷贝的方法
  let obj1 = { name: 11, age: 11, ope: { say: 1, get: 2 }}
  let obj2 = { }
  (1) let obj2 = { ...obj1 } let obj2 = { ...obj1 ,ope:22}
  这个拷贝不彻底,他可以深拷贝基础数据类型,name 等修改不会影响,但是数组、对象不行,ope里面的数据依旧相互影响,但是我们
  可以将这些引用数据类型给修改掉,这样依旧可以实现互不影响   (2) let obj2 = Object.assign({ },obj1,...)
  原理是一样的,也是只对基本数据类型管用,这个灵活度,还不如上面那个   (3) 通过 json 字符串、对象转换的方式
  obj2 = JSON.stringify(obj1) 先转 字符串
  obj2 = JSON.parse(obj2) 再转对象 而且转成字符串以后,还方便 网络传输 、 存储。
   现象二
     var arr1 = [,,];
var arr2 = [,,];
var obj1 = {id:,name:"张三"};
var obj1 = {id:'',name:"张三"};
var arr3 = arr1;
var obj3 = obj1; console.log(arr1 === arr2);//false
console.log(obj1 === obj2);//false
console.log(arr3 === arr1);//true
console.log(obj3 === obj1);//true

  

  1. 现象分析:       

    因为 数组、对象是引用数据类型,变量存储的是地址,真正是数据在地址指针指向的存储单元,所以arr1、arr2的数据是放在不同存储单元里的。直接比较,地址肯定是不同的。而赋值操作 arr3 = arr1 是将地址指针赋值,数组数据还是只放在一个存储单元里面,arr1、arr2 都存储了这个地址,所以直接比较是相等的

2. 如何实现 数组 对象的相等判断
  方法一   转换为字符串再比较
  JSON.stringify(a1) == JSON.stringify(a2)
  或
  a1.toString() == a2.toString()   问题:存在 1 和 '1' ,认为是相同的情况,只能根据自己情况来了
  方法二
function equalJudgment(data1,data2) {
var result = true
if (data1 && data2 && data1.constructor === Array && data2.constructor === Array) {
if (data1.length !== data2.length) {
result = false
} else {
for (var i=0;i<data1.length;i++) {
if (data1[i].constructor === Array && data2[i].constructor === Array){
if (!equalJudgment(data1[i], data2[i])) {
result = false
return result
}
} else if (data1[i].constructor === Object && data2[i].constructor === Object){
if (!equalJudgment(data1[i], data2[i])) {
result = false
return result
}
} else {
if (data1[i] !== data2[i]){
result = false
return result
}
}
}
}
} else if (data1 && data2 && data1.constructor === Object && data2.constructor === Object) {
var key1 = Object.getOwnPropertyNames(data1)
var key2 = Object.getOwnPropertyNames(data2)
if (key1.length !== key2.length) {
result = false
} else {
for (var i=0;i<key1.length;i++) {
if (key2.indexOf(key1[i]) === -1) {
result = false
return result
} else if (data1[key1[i]].constructor === Array && data2[key1[i]].constructor === Array) {
if (!equalJudgment(data1[key1[i]], data2[key2[i]])) {
result = false
return result
}
} else if (data1[key1[i]].constructor === Object && data2[key1[i]].constructor === Object) {
if (!equalJudgment(data1[key1[i]], data2[key1[i]])) {
result = false
return result
}
}else {
if (data1[key1[i]] !== data2[key1[i]]){
result = false
return result
}
}
}
}
} else {
result = 'Input error!'
}
return result
}

  

  以上 js 函数是我自己写的,经过测试没有问题 ,网上有很多实现的方法,但是大多都是无法解析多层数组、对象嵌套的情况 (说实话没啥卵用),但是个人觉得这个方法写的有些啰嗦,抛砖引玉,有更好的方法希望大家不吝分享。   ps:顺便帮我测测bug,虽然各种情况都试过,应该是没问题

总结

  上述的2个现象在码代码过程中应该会经常遇到,特别是处理像  react、Vue 生命周期函数的时候、state使用修改的时候,经常会遇到引用数据类型带来的问题,不经意间就出问题了,希望这些能帮到大家,若有错误,望指出!!!

js数组和对象相等判断、拷贝详解(结合几个现象讲解引用数据类型的趣事)的更多相关文章

  1. js对象浅拷贝和深拷贝详解

    js对象浅拷贝和深拷贝详解 作者:i10630226 字体:[增加 减小] 类型:转载 时间:2016-09-05我要评论 这篇文章主要为大家详细介绍了JavaScript对象的浅拷贝和深拷贝代码,具 ...

  2. js 数组、对象转json 以及 json转 数组、对象

    let jsonObj = $.parseJSON(jsonStr); //json字符串转化成json对象(jq方法) var jsonObj = JSON.parse(jsonStr); //js ...

  3. JS DOM对象控制HTML元素详解

    JS DOM对象控制HTML元素详解 方法: getElementsByName()  获取name getElementsByTagName()  获取元素 getAttribute()  获取元素 ...

  4. vue.js循环for(列表渲染)详解

    vue.js循环for(列表渲染)详解 一.总结 一句话总结: v-for <ul id="example-1"> <li v-for="item in ...

  5. JavaScript对象的property属性详解

    JavaScript对象的property属性详解:https://www.jb51.net/article/48594.htm JS原型与原型链终极详解_proto_.prototype及const ...

  6. js正则实现二代身份证号码验证详解

    js正则实现二代身份证号码验证详解 根据[中华人民共和国国家标准 GB 11643-1999]中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成.排列顺序从左至 ...

  7. vue.js选择if(条件渲染)详解

    vue.js选择if(条件渲染)详解 一.总结 一句话总结: v-if <!DOCTYPE html> <html lang="en"> <head& ...

  8. Angular.js中处理页面闪烁的方法详解

    Angular.js中处理页面闪烁的方法详解 前言 大家在使用{{}}绑定数据的时候,页面加载会出现满屏尽是{{xxx}}的情况.数据还没响应,但页面已经渲染了.这是因为浏览器和angularjs渲染 ...

  9. js keyup、keypress和keydown事件 详解

    js keyup.keypress和keydown事件  详解 js keyup.keypress和keydown事件都是有关于键盘的事件 当一个按键被pressed 或released在每一个现代浏 ...

随机推荐

  1. Jenkins的配置从节点中默认没有Launch agent via Java Web Start选项问题

    Jenkins的配置从节点中默认没有Launch agent via Java Web Start,如下图所示,而这种启动方式在Windows上是最方便的. 如何设置才能让出来呢? 1:打开" ...

  2. jmeter生成html格式接口自动化测试报告

    jmeter生成html格式接口自动化测试报告 jmeter自带执行结果查看的插件,但是需要在jmeter工具中才能查看,如果要向领导提交测试结果,不够方便直观. 笔者刚做了这方面的尝试,总结出来分享 ...

  3. 如何配置adb环境变量

    如何配置adb环境变量? 1.我的电脑---控制面板---高级系统设置 2.点击[高级系统设置],弹出系统属性的弹框, 3.点击[环境变量],弹出环境变量弹框,新建一个系统变量,命名为Android ...

  4. selenium截图

    文件结构 1.DateUtil.py # cncoding = utf-8 import time from datetime import datetime ''' 本文件主要用于获取当前的日期以及 ...

  5. Django—模板

    索引 一.模板语言 1.1 变量 1.2 标签 1.3 过滤器 1.4 自定义过滤器 1.5 注释 二.模板继承 三.HTML转义 四.CSRF 五.验证码 六.反向解析 模板 作为Web框架,Dja ...

  6. 学习笔记_J2EE_SpringMVC_02_注解配置

    SpringMVC注解配置 1.测试环境: 名称 版本 备注 操作系统 Windows10 专业版1809X64   WEB服务器 Tomcat 8.5 X64   浏览器 Google Chrome ...

  7. BFC知识点概括与总结

    什么是BFC?如何生成一个BFC?BFC有什么作用? 一:什么是BFC? 首先了解CSS中两个概念:box和formatting context. Box:CSS布局中的基本单位.一个页面由多个box ...

  8. 几道比较有意思的js面试题

    1.[] ? !![] : ![];输出结果是什么? 1 2 3 4 5 let val = [] ? !![] : ![]; console.log(val);  //true: //之前的错误解释 ...

  9. CF809E Surprise me!

    题解: 一道很套路的题目 首先一个结论 $\phi(xy)=\frac{\phi(x)*\phi(y)*gcd(x,y)}{\phi(gcd(x,y))}$ 这个按照$\phi$的定义很容易知道 然后 ...

  10. 安装SSL证书 and 根域名跳转www域名

    1.安装自签证书 自签证书也就是不被公网认可的证书,可在局域网内进行签名认证,其12306也是自签证书,通过证书+nginx代理web服务器 可以实现https连接  一.使用OpenSSL创建证书 ...