最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

eloquent - Deep Compare JavaScript function - Stack Overflow

programmeradmin0浏览0评论

I'm working my way through the 3rd edition of Eloquent JavaScript and although I've seen one or two various answers on SO that seem almost identical in execution logic to mine that work mine just doesnt seem to no matter how I tweek it.

THE GOAL: create a deep parison function that can pare two objects and determine based on their properties if theyre different instances of the same type of object (same keys and values) regardless of reference...

Can anyone spot the bug in my code?

function deepEqual(a,b){
  if((typeof a=='object'&& a!=null)&&(typeof b=='object'&& b!=null)){
   if(Object.keys(a).length != Object.keys(b).length){return false}    
    for(let key in a){
        if(a[key]==b[key]){
          if(!deepEqual(a[key],b[key])){return false}
        }else{
          return false
        }
    }
   return true
  }else if(a!==b){return false}

  else{return true}
}

var obj = {here: {is: "an"}, object: 2};
console.log(deepEqual(obj, obj));
// → true (reads true currently)
console.log(deepEqual(obj, {here: 1, object: 2}));
// → false (reads false currently)
console.log(deepEqual(obj, {here: {is: "an"}, object: 2}));
// → true (reads false currently)

I'm working my way through the 3rd edition of Eloquent JavaScript and although I've seen one or two various answers on SO that seem almost identical in execution logic to mine that work mine just doesnt seem to no matter how I tweek it.

THE GOAL: create a deep parison function that can pare two objects and determine based on their properties if theyre different instances of the same type of object (same keys and values) regardless of reference...

Can anyone spot the bug in my code?

function deepEqual(a,b){
  if((typeof a=='object'&& a!=null)&&(typeof b=='object'&& b!=null)){
   if(Object.keys(a).length != Object.keys(b).length){return false}    
    for(let key in a){
        if(a[key]==b[key]){
          if(!deepEqual(a[key],b[key])){return false}
        }else{
          return false
        }
    }
   return true
  }else if(a!==b){return false}

  else{return true}
}

var obj = {here: {is: "an"}, object: 2};
console.log(deepEqual(obj, obj));
// → true (reads true currently)
console.log(deepEqual(obj, {here: 1, object: 2}));
// → false (reads false currently)
console.log(deepEqual(obj, {here: {is: "an"}, object: 2}));
// → true (reads false currently)
Share Improve this question edited Sep 25, 2018 at 10:05 icedwater 4,9063 gold badges38 silver badges53 bronze badges asked Feb 11, 2018 at 5:17 user16801user16801 551 silver badge6 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 5

The bug was here:

if (a[key] == b[key])

if they're objects the condition may return false even if they're "equal".

function deepEqual(a, b) {
  if (a && b && typeof a == 'object' && typeof b == 'object') {
    if (Object.keys(a).length != Object.keys(b).length) return false;
    for (var key in a) if (!deepEqual(a[key], b[key])) return false;
    return true;
  } else return a === b
}

var obj = {here: {is: "an"}, object: [2]};
console.log(deepEqual(obj, obj));
// → true 
console.log(deepEqual(obj, {here: 1, object: 2}));
// → false 
console.log(deepEqual(obj, {here: {is: "an"}, object: [2]}));
// → true 

Looks like you just need to tweak your for-loop logic to catch objects like so (using your own logic):

for(let key in a){
  let aValue = a[key]
  let bValue = b[key]

  if (typeof aValue == 'object' && typeof bValue == 'object') {
    // catches nested objects and recursively assesses deep equality
    if(!deepEqual(aValue, bValue)) return false
  }
  else if (aValue !== bValue) {
    // if the values are not objects, catches if they are not equal
    return false
  }
}

You can play with this, here: https://jsbin./wotapezuwo/edit?js,console

You can use below function to deep pare values

 function deepCompare(a,b){
       // shallow check
        if (a === b) return true;
    
        // determining types
        const typeA = Object.prototype.toString.call(a);
        const typeB = Object.prototype.toString.call(b);
    
        // if types are not equal
        if (typeA != typeB) return false;
    
        // paring if object
        if (typeA === '[object Object]') {
            if (Object.keys(a) !== Object.keys(b)) return false;
            for (let key in a)
                if (!deepCompare(a[key], b[key])) return false;
            return true;
        }
    
        // paring if array
        else if (typeA === '[object Array]') {
            if (a.length !== b.length) return false;
            for (let i = 0; i < a.length; i++)
                if (!deepCompare(a[i], b[i])) return false;
            return true;
        }
    
        // paring if map 
        else if (typeA === "[object Map]") {
            if (a.keys().length !== b.keys().length) return false;
            for (let key of a.keys())
                if (!deepCompare(a.get(key), b.get(key))) return false;
            return true;
        }
      
        // paring if sets
        else if (typeA === '[object Set]') {
            let x = [...a], y = [...b];
            return deepCompare(x, y);
        }
      
        // null & undefined checks
        else if (typeA === '[object Undefined]' || typeA === '[object Null]')
            return true;
    
        // nothing matched 
        return false;
    }

let a=[1,'a',{x:[1,2,3], y: new Map([['a',1], ['b', new Set([1,2,3])]])}]
let b=[1,'a',{x:[1,2,3], y: new Map([['a',1], ['b', new Set([1,2,3])]])}]

console.log(deepCompare(a,b)) // true

let c=[1,'a',{x:[1,2,3], y: new Map([['a',1], ['b', new Set([1,2,3])]])}]
let d=[1,'a',{x:[1,2,3], y: new Map([['a',1], ['b', 2]])}]

console.log(deepCompare(c, d)) //false
发布评论

评论列表(0)

  1. 暂无评论