代码取自于underscore.js 1.8.3的isEqual函数。

做了一些小小的修改,主要是Function的比较修改。

自己也加了一些代码解读。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js中两个对象的比较</title><script>
/*
需求难点描述:
数组和对象,都能包含自身,还能包含其它类型。
所以数组之间的比较,要递归。
所以这块代码的设计是:
不能包含自身的,先比较。
然后是数组,对象比较。
特别要注意的是,对象的循环引用。
递归时,要记录递归的路径。
*/
function isEqual(a, b) {var toString = Object.prototype.toString,object_keys = Object.keys,has = function(obj, key) {return obj != null && hasOwnProperty.call(obj, key);};var isFunction = function(fn){return toString.call(fn) == '[object Function]' ? true : false;};    var eq = function(a, b, aStack, bStack) {// Identical objects are equal. `0 === -0`, but they aren't identical.// See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).// 验证0===-0if (a === b) return a !== 0 || 1 / a === 1 / b;// A strict comparison is necessary because `null == undefined`.// null// 验证null == undefinedif (a == null || b == null) return a === b;// Compare `[[Class]]` names.var className = toString.call(a);if (className !== toString.call(b)) return false;switch (className) {// Strings, numbers, regular expressions, dates, and booleans are compared by value.case '[object RegExp]':// RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')case '[object String]':// function虽然是引用,但两个内容一样的funciton应该相等。case '[object Function]':// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is// equivalent to `new String("5")`.return '' + a === '' + b;case '[object Number]':// `NaN`s are equivalent, but non-reflexive.// Object(NaN) is equivalent to NaN// 验证 NaNif (+a !== +a) return +b !== +b;// An `egal` comparison is performed for other numeric values.return +a === 0 ? 1 / +a === 1 / b : +a === +b;case '[object Date]':case '[object Boolean]':// Coerce dates and booleans to numeric primitive values. Dates are compared by their// millisecond representations. Note that invalid dates with millisecond representations// of `NaN` are not equivalent.return +a === +b;}var areArrays = className === '[object Array]';if (!areArrays) {if (typeof a != 'object' || typeof b != 'object') return false;// Objects with different constructors are not equivalent, but `Object`s or `Array`s// from different frames are.var aCtor = a.constructor,bCtor = b.constructor;// 判断顺序// 构造器一致// 构造器为函数// 拥有构造器属性// Function instanceof Function == true// Object instanceof Object == true// Array instanceof Array == falseif (aCtor !== bCtor && !(isFunction(aCtor) && aCtor instanceof aCtor &&isFunction(bCtor) && bCtor instanceof bCtor) && ('constructor' in a && 'constructor' in b)) {return false;}}// Assume equality for cyclic structures. The algorithm for detecting cyclic// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.// Initializing stack of traversed objects.// It's done here since we only need them for objects and arrays comparison.
    aStack = aStack || [];bStack = bStack || [];var length = aStack.length;while (length--) {// 递归才会走到这步 // Linear search. Performance is inversely proportional to the number of// unique nested structures.// 检测循环引用,参考用例如下/*var a = {"str":"string",};a["test"]=a;var b = {"str":"string",};b["test"]=b;console.log (isEqual(a,b));*/if (aStack[length] === a){// 判断b的引用是否也循环,跳出循环引用这个坑return bStack[length] === b;} }// Add the first object to the stack of traversed objects.// 递归压栈
    aStack.push(a);bStack.push(b);// Recursively compare objects and arrays.if (areArrays) {// Compare array lengths to determine if a deep comparison is necessary.
      length = a.length;// 数组长度比较if (length !== b.length) return false;// Deep compare the contents, ignoring non-numeric properties.// 递归比较while (length--) {if (!eq(a[length], b[length], aStack, bStack)) return false;}} else {// Deep compare objects.// 把对象的属性们转换成一个数组var keys = object_keys(a),key;length = keys.length;// Ensure that both objects contain the same number of properties before comparing deep equality.if (object_keys(b).length !== length) return false;while (length--) {// Deep compare each member
        key = keys[length];// b也有a一样的key,则递归if (!(has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;}}// Remove the first object from the stack of traversed objects.// 递归出栈
    aStack.pop();bStack.pop();return true;};return eq(a,b);
}var a = {"str":"ying",
};
a["test"]=a;var b = {"str":"ying",
};
b["test"]=a;console.log (isEqual(a,b));</script>
</head>
<body></body>
</html>

js中两个对象的比较相关推荐

  1. 如何判断JS中两个对象是否相等?

    ① 方法一:通过JSON.stringify(obj)来判断两个对象转后的字符串是否相等 优点:用法简单,对于顺序相同的两个对象可以快速进行比较得到结果 缺点:这种方法有限制就是当两个对比的对象中ke ...

  2. js中两个对象数组如何比对合并

    情景 有时候,从后端的数据并非是可以直接使用渲染的,需要经过处理之后才可使用,比如说以下这种情况 //需要将这个数组中的字段合并,渲染在列表中 const array1 = [{id:1,name:' ...

  3. JavaScript -- 时光流逝(三):js中的 String 对象的方法

    JavaScript -- 知识点回顾篇(三):js中的 String 对象的方法 (1) anchor(): 创建 HTML 锚. <script type="text/javasc ...

  4. js中关于Blob对象的介绍与使用

    js中关于Blob对象的介绍与使用 blob对象介绍 一个 Blob对象表示一个不可变的, 原始数据的类似文件对象.Blob表示的数据不一定是一个JavaScript原生格式 blob对象本质上是js ...

  5. JS中的event 对象详解

    JS中的event 对象详解 JS的event对象 Event属性和方法: 1. type:事件的类型,如onlick中的click: 2. srcElement/target:事件源,就是发生事件的 ...

  6. 你还认为JS中万物皆对象?

    经常在国内的各大网站博客上看到一句话,叫做JS中万物皆对象,那是否真是如此? 那么,我们先来捋一捋JS中的数据类型,JS中的数据类型有下面几种 Undefined Null Boolean Numbe ...

  7. JAVA杂谈 —— 1.2 JS比较两个对象内容是否相同

    JS比较两个对象内容是否相同 -- JAVA 欢迎观看本博客 题目详情 欢迎观看本博客   您好! 这是我编程上遇到的困惑,现在记录下来.如有疏漏与不足之处还请多多指教. 题目详情   在实际开发中, ...

  8. js中的DOM对象和jQuery对象的比较

    1. 二者的不同之处: 通过jQuery获取的元素是一个数组, 数组中包含着原生JS中的DOM对象. 例如, 针对下面的一个div结构: <div id="Box">& ...

  9. js mysql json字符串转数组中_php数据库数据转换为js中的json对象

    / 1.在company数据user表中取出10条数据,保存为数组 2.在将数组转化为json格式,传递给js 3.用json解析器将传递过来的json字符串转化为json对象, 4.用documen ...

最新文章

  1. 16个免费和开源商业智能工具
  2. mysql加锁处理分析_MySQL 加锁处理分析 ---非常牛逼
  3. Qt编程之通过鼠标滚轮事件缩放QGraphicsView里面的Item
  4. menu什么意思中文意思_vigorous什么意思
  5. 速度与激情的Webpack
  6. Java 三大特性之——继承
  7. 基于django和vue的xdh官网设计
  8. 在dom最前面插入_JavaScript中的DOM
  9. Shell脚本学习-阶段二十八-shell练习二
  10. Android开发之多线程编程Thread和Runnable使用
  11. 手工画图和计算机画图的内在联系,浅谈计算机绘图有关的论文(2)
  12. 硬盘功率测试软件,CPU功耗检测
  13. 用canvas画出可爱的哆啦A梦
  14. 齐次线性方程组与非齐次线性方程组的区别
  15. 数据仓库开发工程师岗位要求
  16. 从命令行读入一个字符串,表示一个年份,输出该年的世界杯冠军是哪支球队。如果该 年没有举办世界杯,则输出:没有举办世界杯。...
  17. [技术]使用人工智能玩微信跳一跳
  18. 微博遭鹿晗恋情暴击瘫痪,如何把微博服务器搞炸的?
  19. 2012第27周移动APP推荐
  20. 网络测速全解析之一:自定义View基础知识(八)

热门文章

  1. 完美刷机显示云服务器,完美刷机显示云服务器
  2. Kotlin 协程 + Spring webflux 开发后端
  3. cmd oracle 连接实例_基于winserver的Oracle数据库跨版本下的rman备份恢复
  4. 解决swiper在tab切换时,swiper不生效,以及display:none后,无法自动滑动的问题
  5. linux 提取某一行内容
  6. php 预处理原理,PHP的PDO对象预处理的2种实现方法,实现原理详解
  7. python queue_Python-Queue 入门
  8. Github 精选:13 款炼丹利器,有开源工具包也有超大数据集
  9. Javassist 使用指南(一)
  10. Transact_SQL小手册(各种sql语句大集合)