-
Notifications
You must be signed in to change notification settings - Fork 511
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
【Q598】如何实现一个深比较的函数 deepEqual #614
Comments
function isEqual(x, y) {
if (x === y) {
return true;
} else if ((typeof x === 'object' && x !== null) && (typeof y === 'object' && y !== null)) {
const keysX = Object.keys(x);
const keysY = Object.keys(y);
if (keysX.length !== keysY.length) {
return false;
}
for (const key of keysX) {
if(!isEqual(x[key], y[key])) {
return false;
}
}
return true;
} else {
return false;
}
} |
TODO |
const typeOf = (val) => Object.prototype.toString.call(val).slice(8, -1)
const isFunction = (val) => typeOf(val) === 'Function'
function eq(a, b, aStack, bStack) {
// === 结果为 true 的区别出 +0 和 -0
if (a === b) return a !== 0 || 1 / a === 1 / b
// typeof null 的结果为 object,这里做判断,是为了让有 null 的情况尽早退出函数
if (a == null || b == null) return false
// 判断 NaN
if (a !== a) return b !== b
// 判断参数 a 类型,如果是基本类型,在这里可以直接返回 false
const type = typeof a
if (type !== 'function' && type !== 'object' && typeof b != 'object') {
return false
}
// 更复杂的对象使用 deepEq 函数进行深度比较
return deepEq(a, b, aStack, bStack)
}
function deepEq(a, b, aStack, bStack) {
// a 和 b 的内部属性 [[class]] 相同时 返回 true
const className = typeOf(a)
if (className !== typeOf(b)) return false
switch (className) {
case 'RegExp':
case 'String':
return '' + a === '' + b
case 'Number':
if (+a !== +a) return +b !== +b
return +a === 0 ? 1 / +a === 1 / +b : +a === +b
case 'Date':
case 'Boolean':
return +a === +b
}
const areArrays = className === 'Array'
// 不是数组
if (!areArrays) {
// 过滤掉两个函数的情况
if (typeof a != 'object' || typeof b != 'object') return false
const aCtor = a.constructor,
bCtor = b.constructor
// aCtor 和 bCtor 必须都存在并且都不是 Object 构造函数的情况下,
// aCtor 不等于 bCtor, 那这两个对象就真的不相等啦
if (
aCtor !== bCtor &&
!(
isFunction(aCtor) &&
aCtor instanceof aCtor &&
isFunction(bCtor) &&
bCtor instanceof bCtor
) &&
'constructor' in a &&
'constructor' in b
) {
return false
}
}
aStack = aStack || []
bStack = bStack || []
let length = aStack.length
// 检查是否有循环引用的部分
while (length--) {
if (aStack[length] === a) {
return bStack[length] === b
}
}
aStack.push(a)
bStack.push(b)
// 数组判断
if (areArrays) {
length = a.length
if (length !== b.length) return false
while (length--) {
if (!eq(a[length], b[length], aStack, bStack)) return false
}
}
// 对象判断
else {
let keys = Object.keys(a),
key = -1,
length = keys.length
if (Object.keys(b).length !== length) return false
while (length--) {
key = keys[length]
if (!(b.hasOwnProperty(key) && eq(a[key], b[key], aStack, bStack)))
return false
}
}
aStack.pop()
bStack.pop()
return true
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
No description provided.
The text was updated successfully, but these errors were encountered: