js中两个对象的比较
代码取自于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===-0
if (a === b) return a !== 0 || 1 / a === 1 / b;
// A strict comparison is necessary because `null == undefined`.
// null
// 验证null == undefined
if (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
// 验证 NaN
if (+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 == false
if (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中两个对象的比较的更多相关文章
- 关于比较js中两个对象相等 ==
“如果两个操作数都是对象,则比较他们是不是同一个对象(引用的对象在内存中的地址一样),如果两个操作数都指向同一个对象,则相等操作符返回true,否则,返回false”. 我做了一个例子 functio ...
- JS中的event 对象详解
JS中的event 对象详解 JS的event对象 Event属性和方法:1. type:事件的类型,如onlick中的click:2. srcElement/target:事件源,就是发生事件的 ...
- JavaScript -- 时光流逝(三):js中的 String 对象的方法
JavaScript -- 知识点回顾篇(三):js中的 String 对象的方法 (1) anchor(): 创建 HTML 锚. <script type="text/javasc ...
- js中关于Blob对象的介绍与使用
js中关于Blob对象的介绍与使用 blob对象介绍 一个 Blob对象表示一个不可变的, 原始数据的类似文件对象.Blob表示的数据不一定是一个JavaScript原生格式 blob对象本质上是 ...
- js中如何访问对象和数组
js中如何访问对象和数组 一.总结 一句话总结:js访问对象点和中括号,访问数组的话就是中括号 对象 . [] 数组 [] 1.js访问对象的两种方式? . [] 可以使用下面两种方式访问对象的属性和 ...
- MVC中处理Json和JS中处理Json对象
MVC中处理Json和JS中处理Json对象 ASP.NET MVC 很好的封装了Json,本文介绍MVC中处理Json和JS中处理Json对象,并提供详细的示例代码供参考. MVC中已经很好的封装了 ...
- js中的json对象详细介绍
JSON一种简单的数据格式,比xml更轻巧,在JavaScript中处理JSON数据不需要任何特殊的API或工具包,下面为大家详细介绍下js中的json对象, 1.JSON(JavaScript Ob ...
- 关于js中两种定时器的设置及清除(转载)
1.JS中的定时器有两种: window.setTimeout([function],[interval]) 设置一个定时器,并且设定了一个等待的时间[interval],当到达时间后,执行对应的方法 ...
- JavaScript -- 时光流逝(五):js中的 Date 对象的方法
JavaScript -- 知识点回顾篇(五):js中的 Date 对象的方法 Date 对象: 用于处理日期和时间. 1. Date对象的方法 <script type="text/ ...
随机推荐
- 电脑远程工具:mstsc
外网远程控制:电脑远程连接在开始程序中搜:mstsc 然后直接敲IP地址 工具:dell sonicwall netextender.exe mstsc.exe 内网远程控制:使用TeamVi ...
- 161122、BOM 操作写法示例
浏览器相关信息 // 浏览器信息 navigator.userAgent // Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/ ...
- 161017、SQL必备知识点
经典SQL语句大全 基础 1.说明:创建数据库 CREATE DATABASE database-name 2.说明:删除数据库 drop database dbname 3.说明:备份sql ser ...
- 创建laravel项目时打开浏览器常见错误
1.Whoops, looks like something went wrong. 打开:D:\java\wamp\www\subway\app\config\app.php 修改:'debug' ...
- HDU 2444:The Accomodation of Students(二分图判定+匹配)
http://acm.hdu.edu.cn/showproblem.php?pid=2444 题意:给出边,判断这个是否是一个二分图,并求最大匹配. 思路:先染色法求出是否是一个二分图,然后再匈牙利求 ...
- ftp -i -n -v <<! 其中 -n禁止自动登录到初始连接
<<!说明是输入.如是结束了需要再输入 !例如:ftp -i -n -v <<! 这里的叹号代表是ftp 命令的开始get 文件exit ! 代表ftp的命令 ...
- mysql 关联条件与查询(过滤)条件
mysql用outer join时 on 后边只是关联条件,有时可能会查出无用的记录, 需用where查询条件过滤 五欧诺个的数据. 记录一下
- html+css复习之第2篇 | javascript
1. java 中定义数组和对象: 数组(Array)字面量 定义一个数组: [40, 100, 1, 5, 25, 10] 对象(Object)字面量 定义一个对象: {firstName:&quo ...
- Sumdiv(快速幂+约数和)
Sumdiv Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 16244 Accepted: 4044 Description C ...
- Boring count(字符串处理)
Boring count Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...