zhangxinxu / quiz

小测答题收集区
536 stars 43 forks source link

JS基础测试第29期 #11

Open zhangxinxu opened 5 years ago

zhangxinxu commented 5 years ago

本期为JS基础测试,题目如下:

前两小题只需要考虑值是否原生相等即可。第3题难度加大,形式一样的数组值或者对象值也认为是相等的。

补充:数组 [1, 2] 和 [2, 1] 是不等的。

大家提交回答的时候,注意缩进距离,起始位置从左边缘开始;另外,github自带代码高亮,所以请使用下面示意的格式。

 ```js
// 你的JS代码写在这里
 ```

参与答题即得2积分,第1位答题者额外1积分,精妙实现者额外1积分。

Acongr commented 5 years ago

在网上找了一下解题思路,找到Object.getOwnPropertyNames(a);这个方法,取到对象的键值名

// 第一题--网上找到的解法
// 网上找到的答案
function equalObject1(a, b) {
    var aProps = Object.getOwnPropertyNames(a);
    var bProps = Object.getOwnPropertyNames(b);
    if (aProps.length != bProps.length) {
        return false;
    }
    for (var i = 0; i < aProps.length; i++) {
        var propName = aProps[i];
        if (a[propName] !== b[propName]) {
            return false;
        }
    }
    return true;
}
console.log(equalObject1(obj1, obj2));

我对Object.getOwnPropertyNames()不是很熟,感觉不是很好记,于是想到了用for in 的方法,这样可以取到对象的键值名

// 第一题--- for in 替代getOwnPropertyNames方法答案
function getClassName(obj) {
    var Props = [];
    for(name in obj){
        Props.push(name)
    }
    return Props;
}
function equalObject2(a, b) {
    var aProps = getClassName(a);
    var bProps = getClassName(b);
    if (aProps.length != bProps.length) {
        return false;
    }
    for (var i = 0; i < aProps.length; i++) {
        var propName = aProps[i];
        if (a[propName] !== b[propName]) {
            return false;
        }
    }
    return true;
}
console.log(equalObject2(obj1, obj2));
ghost commented 5 years ago

针对数组类型:首先判断长度是否相等,然后通过取交集,判断交集的长度是否和原数组长度相等。 针对对象类型:首先获取对象的 key 数组,之后对 key 数组 进行数组类型相等判断。

对于 每个 value 来说 先判断数据类型是否相同,如果不同,直接返回 false 如果相同,判断是数组还是对象还是其他类型。

如果是其他类型: 函数做特殊处理:不相等(题目没有提到) 剩下的基本类型进行严格相等判断(此处问题:null 和 undefined 是否需要按照相等来看)

更新:用 Object.getOwnPropertyNames 替代 Object.keys 来获取对象键值

区别:

Object.getOwnPropertyNames 可以获得对象上所有的 key,包含不可枚举 key Object.keys 只能获取可枚举的 key


// 辅助函数,判断数组长度相同
function isSameLength(arr1, arr2) {
    return arr1.length === arr2.length
}

// 辅助函数,获取对象类型
function getType(obj) {
    var type = typeof obj
    if (type === "object") {
        if (obj instanceof Array) {
            return "array"
        }
    }
    return type
}

function equal(ele1, ele2) {
    var type1 = getType(ele1),
        type2 = getType(ele2)
    if (type1 === type2) {
        if (type1 === "array") {
            equalArray(ele1, ele2)
        } else if (type1 === "object") {
            equalObject(ele1, ele2)
        } else if (type1 === "function") {
            return false
        } else {
            if (ele1 !== ele2) {
                return false
            }
        }
    } else {
        return false
    }
    return true
}

function equalObject(obj1, obj2) {
    var keySet1 = Object.getOwnPropertyNames(obj1),
        keySet2 = Object.getOwnPropertyNames(obj2);
    if (!isSameLength(keySet1, keySet2)) {
        return false
    }
    var intersectionKeySet = Array.from(new Set([...keySet1, ...keySet2]))
    if (!isSameLength(intersectionKeySet, keySet1)) {
        return false
    }
    for (var key of intersectionKeySet) {
        var val1 = obj1[key],
            val2 = obj2[key]
        if (!equal(val1, val2)) {
            return false
        }
    }
    return true
}

function equalArray(arr1, arr2) {
    if (!isSameLength(arr1, arr2)) {
        return false
    }
    for (var i = 0; i < arr1.length; i++) {
        var val1 = arr1[i],
            val2 = arr2[i]
        if (!equal(val1, val2)) {
            return false
        }
    }
    return true
}

测试用例:


var ans1 = equalObject({ a: 1, b: 2 }, { b: 2, a: 1 })
var ans2 = equalArray([1, 2], [1, 2])
var ans3 = equalArray([1, 2], [1, '2'])
var ans4 = equal({ a: [1, '2'], b: 2 }, { b: 2, a: [1, '2'] })
var ans5 = equal([1, 2, { a: 1, b: 2 }, 9], [1, 2, { b: 2, a: 1 }, 9])
var ans6 = equal([1, 2, { a: 1, b: 2 }, 9], { a: [1, '2'], b: 2 })
console.table([ans1, ans2, ans3, ans4, ans5, ans6])

image

les-lee commented 5 years ago

震惊,下面的代码竟然可以...

function isRealObject (val) {
  return Object.prototype.toString.call(val) === '[object Object]'
}
function isObject (val) {
  return val !== null && typeof val === 'object'
}
// 1 判断两个对象是否具有相同的形态, 只符合题意, 不做多余考虑
function equalObject (o1, o2) {
  if (o1 === undefined || o2 === undefined) throw "参数不能为undefined或不传";
  if ( !isRealObject(o1)) throw '参数1不是一个对象';
  if ( !isRealObject(o2)) throw '参数2不是一个对象';
  var o1keys = Object.getOwnPropertyNames(o1);
  var o2keys = Object.getOwnPropertyNames(o2);
  if (o1keys.length === o2keys.length) {
    return o1keys.every(function (e, i) {
            return o1[e] === o2[e]
          })
  } else {
    return false;
  }
}

console.log("testo", equalObject({a:''}, {a: ''}));

// 2. 判断两个数组是否具有相同的形态, 只符合题意, 不做多余考虑
function equalArray (arr1, arr2) {
  if (arr1 === undefined || arr1 === undefined) throw "参数不能为undefined或不传";
  if ( !Array.isArray(arr1)) throw '参数1不是一个数组';
  if ( !Array.isArray(arr2)) throw '参数2不是一个数组';

  if (arr1.length === arr2.length) {
    return arr1.every(function (item, index) {
      return item === arr2[index]
    })
  } else {
    return false
  }
}

console.log('testa', equalArray(['2', '2'], ['2', '2']))

//  3. 判断两个值是否具有相同的形态
function equal (arg1, arg2) {
  if (arg1 === null || arg2 === null) throw "参数不能为null";
  if (arg1 === undefined || arg1 === undefined) throw "参数不能为undefined或不穿";
  // 这个方法不够严谨, 但是省字啊
  return JSON.stringify(arg1) === JSON.stringify(arg2)
}
// number 和 string 类型的分辨不出, 而且格式必须要符合 json 格式
console.log("teste", equalArray(["2", {a:1}], ["2", {a:'1'}]));

// 3, 来一个正规一点的...

function regularEqual(a, b) {
    if (a === b) return true;
    var isObjectA = isObject(a);
    var isObjectB = isObject(b);
    if (isObjectA && isObjectB) {
      try {
        var isArrayA = Array.isArray(a);
        var isArrayB = Array.isArray(b);
        if (isArrayA && isArrayB) {
          return a.length === b.length && a.every(function (e, i) {
            return regularEqual(e, b[i])
          })
        } else if (a instanceof Date && b instanceof Date) {
          return a.getTime() === b.getTime()
          // 不做 realObject 的判断的话 这里其实可以把 regexp 也考虑进来, 不过好像有点过分了!
        } else if (!isArrayA && !isArrayB) {
          var keysA = Object.getOwnPropertyNames(a);
          var keysB = Object.getOwnPropertyNames(b);
          return keysA.length === keysB.length && keysA.every(function (key) {
            return regularEqual(a[key], b[key])
          })
        } else {
          return false
        }
      } catch (e) {
        return false
      }
    } else if (!isObjectA && !isObjectB) {
       // 转化成字符串再比较, 这样连 NaN 都是可以覆盖到的
      // zhangxinxu: 有bug,会[1, 2] 等于 [1, '2']
       return String(a) === String(b)
    } else {
      return false
    }
}
console.log(regularEqual([{a:1}], [{a:1}]))
console.log(regularEqual([{a:1}], [{a:'1'}]))
natsu0728 commented 5 years ago
function equalObject(obj1, obj2){
    var keys1 = Object.keys(obj1);
    var keys2 = Object.keys(obj2);
    return keys1.length === keys2.length &&
           keys1.every(key => Object.is(obj1[key], obj2[key]))
}

function equalArray(arr1, arr2){
    return arr1.length === arr2.length &&
           arr1.every((item, index) => Object.is(arr1[index], arr2[index]))
}

// 辅助函数
function testBasic(val){
    // 题目没有提及函数 暂时不处理
    return val === null || typeof val !== 'object'
}

function equal(obj1, obj2){
    // 一个是数组一个是对象
    if (Array.isArray(obj1) ^ Array.isArray(obj2)) return false
    // 都是对象或都是数组
    var keys1 = Object.keys(obj1);
    var keys2 = Object.keys(obj2);
    return keys1.length === keys2.length &&
           keys1.every(key =>{
               var isBasic1 = testBasic(obj1[key]);
               var isBasic2 = testBasic(obj2[key]);
               // 都是基本类型
               if (isBasic1 && isBasic2) return Object.is(obj1[key], obj2[key])
               // 都不是基本类型
               if (!isBasic1 && !isBasic2) return equal(obj1[key], obj2[key])
               // 一个是一个不是
               return false
           })
}
nichoasurey commented 5 years ago
function equalObject(obj1, obj2) {
  return JSON.stringify(obj1) === JSON.stringify(obj2)
}
function equalArray(obj1, obj2) {
  return JSON.stringify(obj1) === JSON.stringify(obj2)
}
function equal(obj1, obj2) {
  if(obj1.sort !== obj2.sort){
    return false
  }
  else{
    return JSON.stringify(sortObj(obj1)) === JSON.stringify(sortObj(obj2))
  }
}
function sortObj(obj) {
  let result = {};
  result.index = Object.keys(obj).sort();
  for(let i =0,lenI =result.index.length;i<lenI;i++){
    if(Object.prototype.toString.call(obj[result.index[i]]) === "[object Object]"){
      result[i+''] = sortObj(obj[result.index[i]])
    }
    else{
      result[i+''] = obj[result.index[i]]
    }
  }
  return result
}
liyongleihf2006 commented 5 years ago
/* 第一题 */
console.log(".......第一题.......");
let obj1 = {a:1,b:2};
let obj2 = {b:2,a:1};
function equalObject(obj1,obj2){
    var key1s = Object.keys(obj1),
        key2s = Object.keys(obj2);
    //若键数量不同,那么直接返回false;
    if(key1s.length!==key2s.length){
        return false;
    }
    //下面的肯定是键数量是相同的了
    return key1s.every(key1=>{
        return obj1[key1]===obj2[key1];
    })
}
console.log(equalObject(obj1,obj2));
/* 第二题 */
console.log(".......第二题.......");
let arr1 = [1,2,5,7,9];
let arr2 = [1,2,5,7,9];
 function equalArray(arr1,arr2){
     if(arr1.length!==arr2.length){
         return false;
     }
     return arr1.every((item,idx)=>{
         return item === arr2[idx]
     })
 }
 console.log(equalArray(arr1,arr2));
 /* 第三题 */
 console.log(".......第三题.......");
 obj1 = {a:[1,'2'],b:2,c:{
     d:1,
     e:[1,2],
     f:'abc'
 }};
 obj2 = {b:2,a:[1,'2'],c:{
    d:1,
    e:[1,2],
    f:'abc'
}};
 arr1 = [1,2,{a:1,b:2},9];
 arr2 = [1,2,{b:2,a:1},9];
 let fn =function(){
     console.log("随便一个函数");
 }
 let obj3 = {a:{
     b:fn
 }};
 let obj4 = {a:{
    b:fn
}}; 
 function equal(obj1,obj2){
     const obj1Type = Object.prototype.toString.call(obj1),
           obj2Type = Object.prototype.toString.call(obj2);
     //类型不同肯定不相等
     if( obj1Type!== obj2Type){
         return false;
     }
     if(obj1Type === "[object Array]"){
         //数组长度不相同肯定不相等
         if(obj1.length!==obj2.length){
             return false;
         }
         return obj1.every((item,idx)=>{
             return equal(item,obj2[idx]);
         })
     }
     if(obj1Type === "[object Object]"){
         let key1s = Object.keys(obj1);
         let key2s = Object.keys(obj2);
         //键的数量不同肯定不相等
         if(key1s.length!==key2s.length){
             return false;
         }
         return key1s.every(key1=>{
             return equal(obj1[key1],obj2[key1]);
         })
     }
     //除了数组和对象外直接判断是否相等就可以了
     return obj1 === obj2;
 }

console.log(equal(obj1,obj2));
console.log(equal(arr1,arr2));
console.log(equal(obj1,arr1));
console.log(equal(obj3,obj4));
Lamenda commented 5 years ago
function equalObject(obj1, obj2){
    const [keys1, keys2] = [Object.keys(obj1), Object.keys(obj2)];
    if(keys1.length !== keys2.length){
        return false;
    }
   for(let i = 0;i<keys1.length;i++){
       let prop = keys1[i];
       if(obj1[prop] !== obj2[prop]){
           return false;
       }
   }
   return true;
}

function equalArray(arr1, arr2){
    if(arr1.length !== arr2.length)
    {
        return false;
    }

    arr1= arr1.sort();
    arr2= arr2.sort();
    for(let i = 0; i<arr1.length; i++){
        if(arr1[i] !== arr2[i]){
            return false;
        }
    }
    return true;
}

function type(a){
    const type = typeof a;
    if (type === "object") {
        if (a instanceof Array) {
            return "array"
        }
    }
    return type
}
function equal(a,b){
    const [type1,type2] = [type(a), type(b)];

    if(type1 === type2){
        if(type1 === "object") {
            equalObject(a,b);
        }else if(type1 === "array") {
            equalArray(a,b);
        }else {
            return a === b;
        }
    }else{
        return false;
    }
    return true;
}
XboxYan commented 5 years ago
//比较数组
function equalArray(arr1,arr2,cb){
    if(arr1.length!=arr2.length){
        return false;
    }
    return arr1.every(function(el,i){
        if(cb){
            return cb(i);
        }
        return el === arr2[i]
    })
}

//比较对象
function equalObject(obj1,obj2,cb){
    var aProps = Object.getOwnPropertyNames(obj1);
    var bProps = Object.getOwnPropertyNames(obj2);
    if (aProps.length !== bProps.length) {
        return false;
    }
    return aProps.every(function(props){
        if(cb){
            return cb(props);
        }
        return obj1[props] === obj2[props]
    })
}

function getType(obj){
    return Object.prototype.toString.call(obj).replace(/\[object (\w+)\]/,"$1");
}

//比较任意类型
function equal(a,b){
    var typeA = getType(a);
    var typeB = getType(b);
    if(typeA !== typeB){
        return false;
    }
    if(typeA === 'Array'){
        return equalArray(a,b,function(index){
            return equal(a[index],b[index]);
        })
    }else if(typeA === 'Object'){
        return equalObject(a,b,function(props){
            return equal(a[props],b[props]);
        })
    }else{
        return a === b;
    }
}

如果仅仅只有第三题,可以直接用Object.keys对数组和对象遍历

运行结果

var a = {a:1,b:{c:12,d:[1,{e:1}]}}
var b = {a:1,b:{c:12,d:[1,{e:1}]}}
var c = {a:1,b:{c:12,d:[1,{e:2}]}}
equal(a,b) //true
equal(a,c) //false
xortm commented 5 years ago

第一题:

function equalObject(obj1, obj2){
    let obj = Object.assign({}, obj1, obj2);
        if(Object.keys(obj1).length !== Object.keys(obj2).length) return false;
    let str = JSON.stringify(obj);
    let str1 = JSON.stringify(obj1);
    if(str == str1) return true;
    return false;
}

第二题

function equalArray(arr1, arr2){
    if(JSON.stringify(arr1) === JSON.stringify(arr2)) return true;
    return false;
}
ZWkang commented 5 years ago
const isArray = v => Object.prototype.toString.call(v) === '[object Array]'
const isObject = v => Object.prototype.toString.call(v) === '[object Object]'
const toString = v => Object.prototype.toString.call(v)
function equalArrayBase(compareFunction) {
    return function (arr1, arr2) {
        if(!isArray(arr1) || !isArray(arr2)) return false
        let len = arr1.length
        try{
            for(let i = 0 ; i < len;) {
                compareFunction(arr1[i], arr2[i])
                i++
            }
            return true
        }catch(e) {
            console.log(e)
            return false
        }
    }
}

function equalObjectBase(compareFunction){
    return function (obj1, obj2) {
        try{
            let obj1keys = Object.keys(obj1);
            let obj2keys = Object.keys(obj2)
            if(obj1keys.length !== obj2keys.length) return false
            for(let i in obj1keys) {
                compareFunction(obj1[obj1keys[i]], obj2[obj1keys[i]])
            }
            return true
        }catch(e) {
            console.log(e)
            return false
        }
    }
}

const equalObject = equalObjectBase((val1, val2) => {
    if(val1 !== val2) {
        throw 'ZWkang'
    }
})

const equalArray = equalArrayBase((val1, val2) => {
    if(val1 !== val2) {
        throw 'ZWkang'
    }
})
const thirdCompare = equalObjectBase((val1, val2) => {
    if(isArray(val1) && isArray(val2)) {
        if (!equalArray(val1, val2)) {
            throw 'ZWkang'
        }
    } else if(val1 !== val2) {
        throw 'ZWkang'
    }
})
const fourCompare = equalArrayBase((val1, val2) => {
    if (isObject(val1) && isObject(val2)) {
        if (!equalObject(val1, val2)) {
            throw 'ZWkang'
        }
    }else if(val1 !== val2) {
        throw 'ZWkang'
    }
})

const equal = function (test1, test2) {
    if (toString(test1) !== toString(test2)) {
        return false
    }
    if (/Object/.test(toString(test1))) {
        return thirdCompare(test1, test2)
    } else if (/Array/.test(toString(test2))) {
        return fourCompare(test1, test2)
    }
    console.log('maybe unsupport type?')
}

var ans1 = equalObject({ a: 1, b: 2 }, { b: 2, a: 1 })
var ans2 = equalArray([1, 2], [1, 2])
var ans3 = equalArray([1, 2], [1, '2'])
var ans4 = equal({ a: [1, '2'], b: 2 }, { b: 2, a: [1, '2'] })
var ans5 = equal([1, 2, { a: 1, b: 2 }, 9], [1, 2, { b: 2, a: 1 }, 9])
var ans6 = equal([1, 2, { a: 1, b: 2 }, 9], { a: [1, '2'], b: 2 })
console.table([ans1, ans2, ans3, ans4, ans5, ans6])
crimx commented 5 years ago
/**
 * 1
 * @param o1 {any}
 * @param o2 {any}
 * @returns {boolean}
 */
function equalObject (o1, o2) {
  if (Object.is(o1, o2)) {
    return true
  }

  if (o1 === null || o2 === null ||
      typeof o1 !== 'object' || typeof o2 !== 'object'
  ) {
    return false
  }

  const keys1 = Object.keys(o1)
  const keys2 = Object.keys(o2)

  if (keys1.length !== keys2.length) {
    return false
  }

  return keys1.every(k => equalObject(keys1[k], keys2[k]))
}

/**
 * 2
 * @param arr1 {any}
 * @param arr2 {any}
 * @returns {boolean}
 */
function equalArray (arr1, arr2) {
  if (Object.is(arr1, arr2)) {
    return true
  }

  if (!Array.isArray(arr1) || !Array.isArray(arr2) ||
      arr1.length !== arr2.length
  ) {
    return false
  }

  return arr1.every(i => equalArray(arr1[i], arr2[i]))
}

/**
 * 3
 * @param o1 {any}
 * @param o2 {any}
 * @returns {boolean}
 */
function equal (o1, o2) {
  if (Object.is(o1, o2)) {
    return true
  }

  if (Array.isArray(o1) && Array.isArray(o2)) {
    if (o1.length !== o2.length) {
      return false
    }
    return o1.every(i => equal(o1[i], o2[i]))
  }

  if (o1 === null || o2 === null ||
      typeof o1 !== 'object' || typeof o2 !== 'object'
  ) {
    return false
  }

  const keys1 = Object.keys(o1)
  const keys2 = Object.keys(o2)

  if (keys1.length !== keys2.length) {
    return false
  }

  return keys1.every(k => equal(keys1[k], keys2[k]))
}
mengxiaoixao commented 5 years ago

//对象比较
function equalObject(obj0,obj1,fn){
    let argKey1 = Object.keys(obj1), argKey0 = Object.keys(obj0);
    if(argKey1.length != argKey0.length){
        return false;
    }else{
        let isEqual = Object.keys(obj1).find((val) => {
            if(fn){
                return !fn(val);
              }
            let ar0 = obj0[val], ar1 = obj1[val];
            return ar0 != undefined ? ar1 !== ar0 : true
        })
        return isEqual == undefined;
    }
}
// 数组比较
function equalArray(arr0,arr1,fn){
    if(arr0.length != arr1.length){
        return false;
    } else {
        let isEqual = arr1.find((val,index) => {
            if(fn){
                return !fn(index);
              }
             let ar0 = arr0[index];
            return ar0 != undefined ? val !== ar0 : true
        })
        return isEqual == undefined;
    }
}
function getType(obj){
    return Object.prototype.toString.call(obj).replace(/\[object (\w+)\]/,"$1");
}
//比较任意类型
function equalAll(arg1,arg2){
    let typeArg1 = getType(arg1),typeArg2 = getType(arg2);
    if( typeArg1 !== typeArg2){
        return false;
    }
    if(typeArg2 === 'Array'){
        return equalArray(arg1,arg2,function(index){
            return equalAll(arg1[index],arg2[index]);
        })
    }else if(typeArg2 === 'Object'){
        return equalObject(arg1,arg2,function(index){
            return equalAll(arg1[index],arg2[index]);
        })
    }else{
        return arg1 === arg2;
    }
}
Kyrohm commented 5 years ago


    // 比较Object对象
    function equalObject(obj1,obj2) {

        obj2 = {...obj2,...obj1}
        let lenObj1 = Object.getOwnPropertyNames(obj1).length
        let lenObj2 = Object.getOwnPropertyNames(obj2).length
        let isSameLen = lenObj1 == lenObj2

        let strObj1 = JSON.stringify(obj1)
        let strObj2 = JSON.stringify(obj2)

        return isSameLen && strObj1 == strObj2
    }

    // 比较Array对象
    function equalArray(arr1,arr2) {

        if(arr1.length != arr2.length) return false

        for(var i=0; i<arr1.length; i++) {
            var isSameType = typeof(arr1[i]) == typeof(arr2[i])
            var isSameValue = arr1[i] == arr2[i]
            if ( !(isSameType && isSameValue) ) return false
        }
        return true
    }
    // 比较组合对象
    function equal(obj1,obj2) {

        for ( item in obj1) {
            let isEqual = true 

            if (obj1[item] instanceof Array) {
                isEqual = equalArray(obj1[item],obj2[item])
            }else if(obj1[item] instanceof Object) {
                isEqual = equal(obj1[item],obj2[item])
            }else {
                isEqual = obj1[item] == obj2[item]
            }

            if (!isEqual) return false 
        }

        return true
    }
NeilChen4698 commented 5 years ago
// zhangxinxu: 补充,应该再加上类型一致性判断,否则[1, 2] 和 {'0': 1, '1': 2} 会认为相等。

let equalObject = (o1, o2) => {
    if (!(o1 instanceof Object) || !(o2 instanceof Object)) {
        return false;
    }
    if (Object.keys(o1).length !== Object.keys(o2).length) {
        return false;
    }
    return Object.keys(o1).every(v => o1[v] === o2[v]);
};

let equalArray = equalObject;

let equal = (o1, o2) => {
    if (!(o1 instanceof Object) || !(o2 instanceof Object)) {
        return false;
    }
    if (Object.keys(o1).length !== Object.keys(o2).length) {
        return false;
    }
    return Object.keys(o1).every(v => {
        if (o1[v] instanceof Object) {
            return equal(o1[v], o2[v]);
        } else {
            return o1[v] === o2[v];
        }
    });
};
anothertempore commented 5 years ago

第一题:

/**
 * 判断两个对象里的元素是否原生相等
 * @param {Object} obj1
 * @param {Object} obj2
 */
function equalObject(obj1, obj2) {
  if (!obj1 && !obj2) return true;
  if (!obj1) return false;
  if (!obj2) return false;

  for (let el in obj1) {
    if (Object.prototype.hasOwnProperty.call(obj2, el)) {
      // nested object
      if (Object.prototype.toString.call(obj1[el]) === '[object Object]') {
        if (!equalObject(obj1[el], obj2[el])) return false;
      } else if (obj1[el] !== obj2[el]) return false;
    } else {
      return false;
    }
  }
  return true;
}

第二题:

/**
 * 判断两个数组里的元素是否原生相等
 * @param {Object} obj1
 * @param {Object} obj2
 */
function equalArray(arr1, arr2) {
  if (!arr1 || arr1.length < 0) return false;
  if (!arr2 || arr2.length < 0) return false;
  if (arr1.length !== arr2.length) return false;

  const getIndex = (arr, target) => arr.findIndex(el => el === target);
  return arr1.every(el1 => getIndex(arr1, el1) === getIndex(arr2, el1));
}

第三题:

/**
 * 判断两个数组或对象是否形态相等
 * @param {Object | Array} val1
 * @param {Object | Array} val2
 */
function equal(val1, val2) {
  if (!val1 && !val2) return true;

  const getType = value => Object.prototype.toString.call(value);
  if (getType(val1) !== getType(val2)) return false;

  const equalArray = (arr1, arr2) => {
    if (!arr1 || arr1.length < 0) return false;
    if (!arr2 || arr2.length < 0) return false;
    if (arr1.length !== arr2.length) return false;

    return arr1.every(target => arr2.findIndex(el => el == target) >= 0);
  };

  const equalObject = (obj1, obj2) => {
    if (!obj1 && !obj2) return true;
    if (!obj1) return false;
    if (!obj2) return false;

    for (let el in obj1) {
      if (Object.prototype.hasOwnProperty.call(obj2, el)) {
        // nested object
        if (getType(obj1[el]) === '[object Object]') {
          if (!equalObject(obj1[el], obj2[el])) return false;
        } else if (getType(obj1[el]) === '[object Array]') {
          if (!equalArray(obj1[el], obj2[el])) return false;
        } else if (obj1[el] !== obj2[el]) return false;
      } else {
        return false;
      }
    }
    return true;
  };

  return getType(val1) === '[object Object]'
    ? equalObject(val1, val2)
    : equalArray(val1, val2);
}
ShineKidd commented 5 years ago

一般场景

JSON.Stringify()

深比对

function equalObj (o1, o2) {
  if (toString.call(o1) !== toString.call(o2)) return false
  if (typeof o1 !== 'object') return o1 === o2
  if(Object.keys(o1).length !== Object.keys(o2).length) return false
  return Object.keys(o1).every(key => 
    equalObj(o1[key], o2[key])
  )
}

特殊情况值

继承

var o1 = Object.create([]), o2 = Object.create({})
o1 instanceof Array // false
o2 instanceof Array // true
equalObj(o1, o2) // true ??

fix: 修复数组 Vs 类数组比较

liulyu commented 5 years ago
    //1
            let obj={a:1,b:2};
            let obj1={b:2,a:2};
            function equalObject(obj1,obj2){
                var prop1 = Object.getOwnPropertyNames(obj1);
                var prop2 = Object.getOwnPropertyNames(obj2);
                if(prop1.length!=prop2.length){
                    return false;
                }

                for (let index = 0; index < prop1.length; index++) {
                    var attr = prop1[index];
                    if(obj1[attr]!=obj2[attr]){
                        return false;
                    }
                }
                return true
            };

            //2
            let arr1=[1,2,5,7,null]
            let arr2=[1,2,5,7,null]
            function equalArray(arr1,arr2){
                if(!Array.isArray(arr1) || !Array.isArray(arr2)){
                    return false;
                };

                if(arr1.length!=arr2.length){
                    return false;
                }

                for (let index = 0; index < arr1.length; index++) {
                    var a  = type(arr1[index]);
                    var b  = type(arr2[index]);

                    if(arr1[index]!=arr2[index] || a!=b){
                        return false;
                    }
                };
                return true;
            }

            function type(a){
                return a==null?"[object Null]" : Object.prototype.toString.apply(a);
            }

            console.log(equalArray(arr1,arr2));

            //3
            function equal(arr1,arr2){
                //debugger
                if(Array.isArray(arr1)&&Array.isArray(arr2)){
                    if(arr1.length!=arr2.length){
                        return false;
                    }
                    for (let index = 0; index < arr1.length; index++) {
                        var a  = type(arr1[index]);
                        var b  = type(arr2[index]);

                        if(a.slice(8,-1)==b.slice(8,-1)=="Object"){
                            if(!equalObject(arr1[index],arr2[index])){
                                return false
                            }
                        }else{
                            if(arr1[index]!=arr2[index] || a!=b){
                                return false;
                            }
                        }
                    }
                }

                else{
                    var prop1 = Object.getOwnPropertyNames(arr1);
                    var prop2 = Object.getOwnPropertyNames(arr2);
                    if(prop1.length!=prop2.length){
                        return false;
                    }

                    for (let index = 0; index < prop1.length; index++) {
                        var attr = prop1[index];
                        var a1=arr1[attr],a2=arr2[attr];
                        if(type(a1)=="[object Array]" &&type(a2)=="[object Array]"){
                            if(!equalArray(a1,a2)){
                                return false
                            }
                        }else{
                            if(a1!=a2){
                                return false
                            }
                        }
                    }
                }
                return true
            }
silverWolf818 commented 5 years ago
TTtuntuntutu commented 5 years ago
//预处理字符串化
function preTreatment(value){
  //基础类型直接返回
  if(typeof value!=="object") return typeof value + String(value);
  if(Object.is(value,null)) return "null" + String(value);

  //引用类型
  //数组
  if(Object.prototype.toString.call(value)==="[object Array]"){
    return value.map(v=>preTreatment(v)).join(",");
  }

  //对象
  if(Object.prototype.toString.call(value)==="[object Object]"){
    const keys = Object.getOwnPropertyNames(value).sort();

    return keys.map(k=>{
      if(typeof value[k]!=="object") return `${k}:${preTreatment(value[k])}`;
      return preTreatment(value[k]);
    }).join(",")
  }
}

//返回比较结果
function equal(v1,v2){
  return preTreatment(v1)===preTreatment(v2);
}
uaison commented 5 years ago

修改

function isSameType(obj1, obj2) { // 是否相同类型
    return Object.prototype.toString.call(obj1) === Object.prototype.toString.call(obj2);
}

function equalObject(obj1, obj2) { // 第一题
  if(!isSameType(obj1, obj2)) return false;
  let keys1 = Object.keys(obj1);
  let keys2 = Object.keys(obj2);
  return keys1.length === keys2.length && keys1.every(key => obj1[key] === obj2[key]);
}

function equalArray(arr1, arr2) { // 第二题
  return arr1.length===arr2.length && arr1.every((item, index) => item === arr2[index]);
}

function equal(arg1, arg2) { // 第三题
  if (!isSameType(arg1, arg2)) return false;
  let keys1 = Object.keys(arg1);
  let keys2 = Object.keys(arg2);
  return keys1.length === keys2.length && keys1.every(key => {
    if(arg1[key] instanceof Object) return equal(arg1[key], arg2[key]);
    return arg1[key] === arg2[key];
  })
}

错误答案: 第一题JSON.stringify问题,第二题没漏虑数组长度不相等,第三题问题集合前两题。。。

function equalObject(obj1, obj2) { // 第一题
  let str1 = JSON.stringify(obj1);
  let str2 = JSON.stringify(obj2);
  if (str1 === str2) return true;
  if (str1.length != str2.length) return false;
  let a = str1.substring(1, str1.length - 1);
  let b = str2.substring(1, str2.length - 1);
  return a.split(',').every(item => b.indexOf(item) > -1)
}

function equalArray(arr1, arr2) { // 第二题
  return arr1.every((item, index) => item === arr2[index]);
}

function isObject(obj) {  // 是否对象
  return Object.prototype.toString.call(obj) === '[object Object]';
}

function isArray(arr) { // 是否数组
  return Object.prototype.toString.call(arr) === '[object Array]';
}

function equal(arg1, arg2) { // 第三题
  if (!(isObject(arg1) && isObject(arg2) || isArray(arg1) && isArray(arg2))) return false;
  if (isArray(arg1) && isArray(arg2))
      return arg1.every((item, index) => item === arg2[index] || arg2[index] && equalObject(item, arg2[index]));
  if (isObject(arg1) && isObject(arg2)) {
    let keys1 = Object.keys(arg1);
    let keys2 = Object.keys(arg2);
    if (keys1.length !== keys2.length) return false;
    return keys1.every(key => {
      if (isObject(arg1[key]))
          return equalObject(arg1[key], arg2[key]);
      if (isArray(arg1[key]))
          return equalArray(arg1[key], arg2[key]);
      return arg1[key] === arg2[key];
    })
  }
}
dengjiarong1225 commented 5 years ago

第一次交作业喔,张大哥会翻我牌子吗 😄

 /**判断两个数组/对象是否相等(1,2,3题均可适用)
   * @param {object/array} o1 
   * @param {object/array} o2
   * returns {boolean}  
   */
   function equalObject (o1, o2) {
       let o1Keys = Object.keys(o1)  
       let o2Keys = Object.keys(o2)

       // 如果 length 不相等,直接返回 false
       if (o1Keys.length !== o2Keys.length) return false

       let result = o1Keys.every(ele => {
         // 如果 o2 里面没有 o1 的属性,返回false
         if (!o2Keys.includes(ele)) return false

         // 嵌套有 object/array,则再次调用equalObject
         if (o1[ele].length !== 1) return equalObject(o1[ele], o2[ele])

         // 判断 o1,o2 在该属性下,属性值是否相等
         return o1[ele] === o2[ele]
       })

     return result
   }
yyjazsf commented 5 years ago

React 有个纯函数比较,代码差不多:)

Jon-Millent commented 5 years ago

一个函数搞定,函数第三个参数不传


function eqal(obja, objb, same) {
  // 递归对象

  let type = Object.prototype.toString.call(obja)
  let sameObj = same || {
    isSame: true
  }
  if(typeof obja !== 'object') {
    sameObj.isSame = (obja === objb)
  } else {
    try {
      for(let i in obja) {
        if(type === "[object Array]" || type === "[object Object]") {
          eqal(obja[i], objb[i], sameObj)
        } else {
          sameObj.isSame = (obja[i] === objb[i])
          console.log(obja[i], objb[i])
        }
      }
    } catch(e) {
      console.log(e)
      sameObj.isSame = false
    }
  }

  return sameObj.isSame

}
thewindsword commented 5 years ago

1. EqualObject

function equalObject(a, b) {
  let resultNum = 0;
  const typeA = Object.prototype.toString.call(a);
  const typeB = Object.prototype.toString.call(b);
  if (typeA !== '[object Object]' && (typeA !== typeB)) {
    throw Error('function type error');
  }
  let keyA = Object.keys(a);
  let keyB = Object.keys(b);
  if (keyA.length !== keyB.length) return false;
  for (let i = 0;i < keyA.length;i++) {
    let targetKey = keyA[i];
    if (b[targetKey] == a[targetKey]) {
      resultNum++;
    } else {
      return false;
    }
  }
  return resultNum === keyA.length;
}

let obj1 = {
  a: 1,
  b: 2
};
let obj2 = {
  a: 1,
  b: 2
};
// equalObject(obj1, obj2);
console.log("equalObject(obj1, obj2)", equalObject(obj1, obj2));
console.log("equalObject({a:[]}, {a:[]})", equalObject({a:[]}, {a:[]}));

2. EqualArray

function equalArray(a, b) {
  const typeA = Object.prototype.toString.call(a);
  const typeB = Object.prototype.toString.call(b)
  if (typeA !== '[object Array]' && (typeA !== typeB)) {
    throw Error('function type error');
  }
  if (a.length !== b.length) return false;
  for (let i = -1, item = a[i];item=a[++i];){
    if (item !== b[i]) {
      return false;
    }
  }
  return true;
}

let arr1 = [1, 2, 5, 7, 9];
let arr2 = [1, 2, 5, 7, 9];
console.log('equalArray(arr1, arr2)', equalArray(arr1, arr2));
console.log('equalArray([1, 2], [1, 2])', equalArray([1, 2], [1, 2]));
console.log('equalArray([2, 1], [1, 2])', equalArray([2, 1], [1, 2]));
console.log("equalArray([1, 2], ['1', '2'])", equalArray([1, 2], ['1', '2']));

3. Equal

function equal(a, b) {
  const typeA = Object.prototype.toString.call(a);
  const typeB = Object.prototype.toString.call(b);
  if (typeA === typeB) {
    if (typeA === '[object Object]') {
      // Object
      let resultNum = 0;
      let keyA = Object.keys(a);
      let keyB = Object.keys(b);
      if (keyA.length !== keyB.length) return false;
      for (let i = 0;i < keyA.length;i++) {
        let targetKey = keyA[i];
        if (equal(b[targetKey], a[targetKey])) {
          resultNum++;
        } else {
          return false;
        }
      }
      return resultNum === keyA.length;
    } else if (typeA === '[object Array]') {
      // Array
      if (a.length !== b.length) return false;
      for (let i = -1, item = a[i];item=a[++i];){
        if (!equal(item, b[i])) {
          return false;
        }
      }
      return true;
    } else {
      // Not Support
      return a === b;
    }
  } else {
    return false;
  }
}

let obj1 = { a: [1, '2'], b: 2};
let obj2 = { b: 2, a: [1, '2']};
let arr1 = [1, 2, { a: 1, b: 2 }, 9];
let arr2 = [1, 2, { b: 2, a: 1 }, 9];

console.log("equal(obj1, obj2)", equal(obj1, obj2));
console.log("equal(arr1, arr2)", equal(arr1, arr2));
console.log("equal(obj1, arr1)", equal(obj1, arr1));
ylfeng250 commented 5 years ago
// 第一题
function equalObject(obj1, obj2) {
  // 先判断是否是纯对象
  if (!isObject(obj1) || !isObject(obj2)) {
    return false
  }
  const keys1 = Object.getOwnPropertyNames(obj1)
  const keys2 = Object.getOwnPropertyNames(obj2)

  if (keys1.length !== keys2.length) {
    return false
  }
  return keys1.every((key) => {
    // 里面的属性不一致
    if (keys2.indexOf(key) === -1) {
      return false
    }
    // 判断属性值是否相等
    return obj1[key] === obj2[key]
  })
}
// 判断是否为对象
function isObject(obj) {
  return Object.prototype.toString.call(obj) === '[object Object]'
}

// 第二题
function equelArray(arr1, arr2) {
  // 判断是否是数组
  if (!Array.isArray(arr1) || !Array.isArray(arr2)) {
    return false
  }
  // 判断数组的长度是否相等
  if (arr1.length !== arr2.length) {
    return false
  }
  return arr1.every((val,index) => {
    return val === arr2[index]
  })
}

// 第三题

function equal (arg1, arg2) {
  // 先判断类型是否一致
  if (Object.prototype.toString.call(arg1) !== Object.prototype.toString.call(arg2)) {
    return false
  }
  if (isObject(arg1)) {
    const keys1 = Object.getOwnPropertyNames(arg1)
    const keys2 = Object.getOwnPropertyNames(arg2)
    // 长度一致
    if (keys1.length !== keys2.length) {
      return false
    }
    return keys1.every((key) => {
      if (keys2.indexOf(key) === -1) {
        return false
      }
      // 类型不一致
      if (Object.prototype.toString.call(arg1[key]) !== Object.prototype.toString.call(arg2[key])) {
        return false
      }
      return equal(arg1[key], arg2[key])
    })
  }
  if (Array.isArray(arg1)) {
    // 判断数组长度
    if (arg1.length !== arg2.length) {
      return false
    }
    return arg1.every((val, index) => {
      return equal(val, arg2[index])
    })
  }
  // 判断数组和对象以外的相等
  return arg1 === arg2
}

function test() {
  console.log('第一题测试')
  let obj1 = {a: 1, b: 2}
  let obj2 = {a: 1, b: 2}
  let obj3 = {a:1, b:'2'}
  console.log(equalObject(obj1, obj2))
  console.log(equalObject(obj1, obj3))
  console.log('第二题测试')
  let arr1 = [1, 2]
  let arr2 = [2, 1]
  console.log(equelArray(arr1, arr2))
  console.log('第三题测试')
  let obj4 = { a: [1, '2'], b: 2}
  let obj5 = { b: 2, a: [1, '2']}
  let arr3 = [1, 2, { a: 1, b: 2 }, 9]
  let arr4 = [1, 2, { b: 2, a: 1 }, 9]
  console.log(equal(obj4, obj5))
  console.log(equal(arr3, arr4))
  console.log(equal(obj4, arr4))
}

test()
y389278443z commented 5 years ago
    function equal(obj1, obj2) {
        if (obj1 === obj2) return true;
        if (Object.keys(obj1).length !== Object.keys(obj2).length) return false;

        for (let i in obj1) {
            if (!obj2[i])  return false;
            if (Array.isArray(obj1[i]) && Array.isArray(obj2[i])) {
                for (let index of obj1[i]) {
                    if (obj1[i][index] !== obj2[i][index]) return false;
                }
            } else if (typeof obj1[i] === 'object' && typeof obj2[i] === 'object') {
                var isEqual = equal(obj1[i], obj2[i]);
                if (!isEqual) return false;
            } else if (obj1[i] !== obj2[i]) {
                return false;
            }
        }
        return true;
    }
frankyeyq commented 5 years ago

1. equalObject

function equalObject(obj1, obj2) {
    var flag = true;
    var len1 = Object.keys(obj1).length;
    var len2 = Object.keys(obj2).length;
    if (len1 !== len2) return false;
    flag = !Object.keys(obj1).some(key => obj1[key] !== obj2[key]);
    return flag;
}

2.equalArray

function equalArray(arr1, arr2) {
    var len1 = arr1.length;
    var len2 = arr2.length;
    if (len1 !== len2) return false;
    return !arr1.some((item, index) => item !== arr2[index]);
}

3.equal

function equal(obj1, obj2) {
    var _toString = Object.prototype.toString;

    function isPlainObject (obj) {
        return _toString.call(obj) === '[object Object]'
    }

    function equalType(obj1, obj2) {
        return _toString.call(obj1) === _toString.call(obj2);
    }

    if (!equalType(obj1, obj2)) return false;

    if (Array.isArray(obj1)) {
        var len1 = obj1.length;
        var len2 = obj2.length;
        if (len1 !== len2) return false;
        return !obj1.some((_, index) => {
            var o1 = obj1[index];
            var o2 = obj2[index];
            return !equal(o1, o2);
        });
    } else if (isPlainObject(obj1)) {
        var keys1 = Object.keys(obj1);
        var keys2 = Object.keys(obj2);
        if (keys1.length !== keys2.length) return false;
        return !keys1.some(key => {
            var o1 = obj1[key];
            var o2 = obj2[key];
            return !equal(o1, o2)
        });
    } else {
        return obj1 === obj2;
    }    
}
SummerLiu95 commented 5 years ago

在网上找了一下解题思路,找到Object.getOwnPropertyNames(a);这个方法,取到对象的键值名

// 第一题--网上找到的解法
// 网上找到的答案
function equalObject1(a, b) {
   var aProps = Object.getOwnPropertyNames(a);
   var bProps = Object.getOwnPropertyNames(b);
   if (aProps.length != bProps.length) {
       return false;
   }
   for (var i = 0; i < aProps.length; i++) {
       var propName = aProps[i];
       if (a[propName] !== b[propName]) {
           return false;
       }
   }
   return true;
}
console.log(equalObject1(obj1, obj2));

我对Object.getOwnPropertyNames()不是很熟,感觉不是很好记,于是想到了用for in 的方法,这样可以取到对象的键值名

// 第一题--- for in 替代getOwnPropertyNames方法答案
function getClassName(obj) {
   var Props = [];
   for(name in obj){
      Props.push(name)
   }
   return Props;
}
function equalObject2(a, b) {
   var aProps = getClassName(a);
   var bProps = getClassName(b);
   if (aProps.length != bProps.length) {
       return false;
   }
   for (var i = 0; i < aProps.length; i++) {
       var propName = aProps[i];
       if (a[propName] !== b[propName]) {
           return false;
       }
   }
   return true;
}
console.log(equalObject2(obj1, obj2));

使用 for in 遍历对象字段是不是需要去除原型链对象的字段吧

PatrickLh commented 5 years ago
// 1
function equal(obj1, obj2) {
  if (obj1 === obj2) {
    return true
  } else {
    if (Object.keys(obj1).sort().toString() === Object.keys(obj2).sort().toString()) {
     for (let prop in obj1) {
        return obj1[prop] === obj2[prop]
      }
    } else {
      return false
    }
    return true
  }
}
// 2 
function equalArray(arr1, arr2) {
  if (arr1 instanceof Array && arr2 instanceof Array && arr1.length === arr2.length) {
    for(let i = 0; i < arr1.length; i++) {
      if (arr1[i] !== arr2[i]) {
        return false
      }
    }
    return true
  }
  return false
}
// 3
function equalAll(obj1, obj2) {
  if (obj1 === obj2) {
    return true
  }
  if (obj1 instanceof Array && obj2 instanceof Array && obj1.length === obj2.length) {
    for(let i = 0; i < obj1.length; i++) {
      if (!equalAll(obj1[i], obj2[i])) {
        return false
      }
    }
    return true
  }
  if (typeof obj1 === 'object' && typeof obj2 === 'object') {
    if (Object.keys(obj1).sort().toString() === Object.keys(obj2).sort().toString()) {
      for (let prop in obj1) {
        if(!equalAll(obj1[prop], obj2[prop])) {
          return false
        }
      }
      return true
    }
  }
  return false
}
lineforone commented 5 years ago
// 1
function equalObject(obj1,obj2) {
    if (obj1.length !== obj2.length) {
        return false;
    }

    let equalBool = true;
    for (let key in obj1) {
        if(obj1.key !== obj2.key){
            equalBool = false
            return false
        }
    }

    return equalBool
}

// 2
function equalArray(arr1,arr2) {
    if (obj1.length !== obj2.length) {
        return false;
    }

    let equalBool = true;
    for (let i=0;i<arr1.length;i++) {
        if(arr1[i] !== arr2[i]){
            equalBool = false
            return false
        }
    }

    return equalBool
}

// 3
function equal(obj1,obj2) {
    // 简单类型直接比较
    if(typeof obj1 !== 'object'  || typeof obj2 !== 'object'){
        return obj1 === obj2
    }

    // 复杂类型先判断是否为同一类型
    if(Array.isArray(obj1) !== Array.isArray(obj2)){
        return false
    }

    let equalBool = true;
    if(Array.isArray(obj1)){
        // 数组比较
        for (let i=0;i<obj1.length;i++) {
            if(typeof obj1 == 'object'){
                if(!equal(obj1[i],obj2[i])){
                    return false
                }
            }else if(obj1[i] !== obj2[i]){
                equalBool = false
                return false
            }
        }
    }else{
        // 对象比较
        for (let key in obj1) {
            if(typeof obj1 == 'object'){
                if(!equal(obj1.key,obj2.key)){
                    return false
                }
            }else if(obj1.key !== obj2.key){
                equalBool = false
                return false
            }
        }
    }
    return equalBool
}
youmeigc commented 5 years ago

// 第一次作业,希望大大翻牌 let obj1 = {a: 1, b: {}}; let obj2 = {a: 1,b: {}}; let arr1 = [1, 2, 5, 7, 9]; let arr2 = [1, 2, 5, 7, 9]; // 第一题 function equalObject(obj1, obj2) { if (!(/Object]$/).test(Object.prototype.toString.call(obj1)) || !(/Object]$/).test(Object.prototype.toString.call( obj2))) { console.error('参数必须均为对像类型') return } let keys1 = Object.keys(obj1); // obj1的属性数组 // 先判断是否有同样多的属性,不相同则返回false if (keys1.length !== Object.keys(obj2).length) { return false } if (!keys1.length) { return true } // 判断每个属性值是否相等 for (let val of keys1) { if (obj1[val] != obj2[val]) { return false } if (obj1[val] == obj2[val] && !obj2.hasOwnProperty(val)) { // obj2中是否含有此属性,以防obj1中此属性的值是undefined或null return false } } return true }

// 第二题
function equalArray(arr1, arr2) {
  if (!(/Array\]$/).test(Object.prototype.toString.call(arr1)) || !(/Array\]$/).test(Object.prototype.toString.call(
      arr2))) {
    console.error('参数必须均为数组类型')
    return
  }
  // 判断长度是否相等
  if (arr1.length !== arr2.length) {
    return false
  }
  if (!arr1.length) {
    return true
  }
  for (let i = 0; i < arr1.length; i++) {
    if (arr1[i] != arr2[i]) {
      return false
    }
  }
  return true
}

// 第三题
function equal(temp1, temp2) {
  if (Object.prototype.toString.call(temp1) != Object.prototype.toString.call(temp2)) {
    return false
  }
  if ((/Object\]$/).test(Object.prototype.toString.call(temp1))) { // 对像
    let keys1 = Object.keys(temp1); // temp1的属性数组
    // 先判断是否有同样多的属性,不相同则返回false
    if (keys1.length !== Object.keys(temp2).length) {
      return false
    }
    if (!keys1.length) {
      return true
    }
    // 判断每个属性值是否相等
    for (let val of keys1) {
      if (temp1[val] != temp2[val]) {
        if(!equal(temp1[val],temp2[val])){
          return false
        }
      }
      if (temp1[val] == temp2[val] && !temp2.hasOwnProperty(val)) { // temp2中是否含有此属性,以防temp1中此属性的值是undefined或null
        return false
      }
    }
    return true
  }
  if ((/Array\]$/).test(Object.prototype.toString.call(temp1))) { // 数组
    let temp = 0; // 计录多少次相等
    // 判断长度是否相等
    if (temp1.length !== temp2.length) {
      return false
    }
    if (!arr1.length) {
      return true
    }
    for (let i = 0; i < temp1.length; i++) {
      if (temp1[i] != temp2[i]) {
        if(!equal(temp1[i],temp2[i])){
          return false
        }
      }
    }
    return true
  }
  return temp1 == temp2
}

console.log(equalObject({
  a: 1,
  b: 2
}, {
  b: 1,
  a: 1
}))
console.log(equalArray([1, 2], [1, 2]))
console.log(equal({
  a: 1,
  b:[1,3]
}, {
  b: [1,3],
  a: 1
}))
sghweb commented 5 years ago
 // 三个题目统一一个函数处理
    function equalAll(obj1,obj2){
      if(Object.keys(obj1).length!=Object.keys(obj2).length){
        return false
      }
      for(let index of Object.keys(obj1)){
        if(obj2[index].constructor == obj1[index].constructor){
          if(typeof obj2[index] != "object"){
            if(!Object.is(obj2[index],obj1[index])){ 
              return false
            }
          }
        }else{
          return false
        }
      }
      return true
    }
JasonSubMara commented 5 years ago

第一题

function equals(x, y) {
        var f1 = x instanceof Object;
        var f2 = y instanceof Object;
        if (!f1 || !f2) {
            return x === y
        }
        if (Object.keys(x).length !== Object.keys(y).length) {
            return false
        }
        var newX = Object.keys(x);
        for (var p in newX) {
            p = newX[p];
            var a = x[p] instanceof Object;
            var b = y[p] instanceof Object;
            if (a && b) {
                equals(x[p], y[p])
            } else if (x[p] != y[p]) {
                return false;
            }
        }
        return true;
    }

image

xunzhaoshitouyu commented 5 years ago

获取数据类型

function getType(param) {
  // 0 代表数组,1代表对象,2代表基本数据类型
  var type = Object.prototype.toString.call(param);
  if (type === '[object Array]') {
    return 0;
  } else if (type === '[object Object]') {
    return 1;
  } else {
    return 2;
  }
};

第一题

function equalObject (obj1, obj2) {
  var equal;
  var obj1Keys = Object.keys(obj1);
  var obj2Keys = Object.keys(obj2);
  if (obj1Keys.length === obj2Keys.length) {
    // tslint:disable-next-line:forin
    equal = true;
    for (var index in obj1Keys) {
      if (obj1[obj1Keys[index]] !== obj2[obj1Keys[index]]) {
        equal = false;
        break;
      }
    }
  } else {
    equal = false;
  }
  return equal;
};

第二题

function equalArray(arr1, arr2) {
  var equal;
  if (arr1.length === arr2.length) {
    equal = true;
    // tslint:disable-next-line:forin
    for (var index in arr1) {
      if (arr1[index] !== arr2[index]) {
        equal = false;
        break;
      }
    }
  } else {
    equal = false;
  }
  return equal;
};

第三题

function equal(param1, param2) {
  var equal;
  // 判断传入的参数是否是数组
  var p1Type = this.getType(param1);
  var p2Type = this.getType(param2);
  if (p1Type === 0 && p2Type === 0) {
    equal = true;
    if (param1.length === param2.length) {
      // tslint:disable-next-line:forin
      for (var index in param1) {
        // 判断数组中元素的数据类型
        var p1ItemType = this.getType(param1[index]);
        var p2ItemType = this.getType(param2[index]);
        if (p1ItemType === p2ItemType) {
          if (p1ItemType === 2) {
            if (param1[index] !== param2[index]) {
              equal = false;
              break;
            }
          }
        } else {
          equal = false;
        }
      }
    } else {
      equal = false;
    }
  } else if (p1Type === 1 && p2Type === 1) {
    equal = true;
    var p1Keys = Object.keys(param1);
    var p2Keys = Object.keys(param2);
    if (p1Keys.length === p2Keys.length) {
      // tslint:disable-next-line:forin
      for (var index in p1Keys) {
        var p1ItemType = this.getType(param1[p1Keys[index]]);
        var p2ItemType = this.getType(param2[p1Keys[index]]);
        if (p1ItemType === p2ItemType) {
          if (p1ItemType === 2) {
            if (param1[p1Keys[index]] !== param2[p1Keys[index]]) {
              equal = false;
              break;
            }
          }
        } else {
          equal = false;
        }
      }
    } else {
      equal = false;
    }
  } else {
    equal = false;
  }
  return equal;
};
DFLovingWM commented 5 years ago

注释写在代码中了。关键是第3个问题,需要额外使用两个数组,以避免循环引用引起的递归爆栈。

/**
 * 题目1:
 * 判断两个对象是否等价(类似浅拷贝)
 */
function equalObject (A, B) {
  if (getType(A) !== 'Object' || getType(B) !== 'Object') { // 防止非纯对象调用,比如数组
    return false
  }

  let [aKeys, bKeys] = [Reflect.ownKeys(A), Reflect.ownKeys(B)]
  if (aKeys.length !== bKeys.length) { // 如果key数目不同 => 不等价
    return false
  }

  for (const key of aKeys) {
    if (!B.hasOwnProperty(key)) { // A中存在B没有的key => 不等价
      return false
    }
    if (A[key] !== B[key]) { // 题目要求:只需原生相等
      return false
    }
  }

  return true
}

/**
 * 题目2:
 * 判断两个数组是否等价(类似浅拷贝)
 */
function equalArray (A, B) {
  if (!Array.isArray(A) || !Array.isArray(B)) { // 防止非数组对象调用,比如“类数组对象”
    return false
  }
  if (A.length !== B.length) { // 长度不同 => 不等价
    return false
  }

  for (let i = 0; i < A.length; ++i) {
    if ( // 考虑空slot的情况(否则空slot与undefined全等了)
      (A.hasOwnProperty(i) && !B.hasOwnProperty(i)) ||
      (!A.hasOwnProperty(i) && B.hasOwnProperty(i))
    ) {
      return false
    }

    if (A[i] !== B[i]) {
      return false
    }
  }

  return true
}

/**
 * 题目3:
 * [递归法]判断对象/数组是否深度等价(类似于assert中的deepEqual)
 * @param {Object | Array} A
 * @param {Object | Array} B
 * @param {Array} aList 存储比较过的A对象
 * @param {Array} bList 存储比较过的B对象
 * @returns {boolean} 是否深度等价
 */
function equal (A, B, aList = [], bList = []) {
  let [aType, bType] = [getType(A), getType(B)]
  if (aType !== bType) { // 类型不相同,则说明这一层不等价
    return false
  }
  if (!['Object', 'Array'].includes(aType)) { // 如果不是纯对象/数组类型,则直接比较引用(偷懒,其实这里还可以扩展,比如Date类型啥的)
    return A === B
  }

  /*
   * 避免递归爆栈的关键:
   * 如果aList、bList存在(A,B)这一对,说明:A与B是“暂时”等价的,
   * 可以直接返回。
   */
  let hasCompared = aList.some((a, index) => {
    return a === A && bList[index] === B
  })
  if (hasCompared) {
    return true
  }

  aList.push(A)
  bList.push(B)

  let result = true
  if (aType === 'Object') { // 如果是对象类型...
    let [aKeys, bKeys] = [Reflect.ownKeys(A), Reflect.ownKeys(B)]
    if (aKeys.length !== bKeys.length) {
      result = false
    }
    if (result) {
      for (const key of aKeys) {
        if (
          !B.hasOwnProperty(key) || // 如果B没有这个key,则不等价
          !equal(A[key], B[key], aList, bList) // 关键:递归地 检查是否等价
        ) {
          result = false
          break
        }
      }
    }
  } else if (aType === 'Array') { // 如果是数组类型...
    if (A.length !== B.length) {
      result = false
    }
    if (result) {
      for (let i = 0; i < A.length; ++i) {
        if (
          ((A.hasOwnProperty(i) && !B.hasOwnProperty(i)) || (!A.hasOwnProperty(i) && B.hasOwnProperty(i))) || // 如果存在一个key,使得A有B无或相反,则二者不等价
          (!equal(A[i], B[i], aList, bList)) // 同理,递归
        ) {
          result = false
          break
        }
      }
    }
  }

  aList.pop()
  bList.pop()

  return result
}

// 获取变量/对象的类型
function getType (x) {
  let tmp = Object.prototype.toString.call(x)
  return tmp.slice(8, tmp.length - 1)
}
hutuchong9527 commented 5 years ago
/*第一题*/
//浅匹配两个对象是否相等
function equalObject(a, b) {
    //核实参数是否是对象
    if (typeof a === 'object' && typeof b === 'object') {
        let aArr = Object.keys(a), bArr = Object.keys(b);
        //比对参数属性个数是否相等
        if (aArr.length !== bArr.length) {
            return false;
        } else {
            //比对参数属性值是否全等
            for (let i = 0, len = aArr.length; i < len; i++) {
                let x = aArr[i];
                if (a[x] !== b[x]) {
                    return false
                }
            }
            return true;
        }
    } else {
        throw '参数必须都为对象';
    }
}
/*第二题*/
//浅匹配两个数组是否相等
function equalArray(a,b){
    //核实参数是否是数组
    if ( a instanceof Array && b instanceof Array) {
        //比对参数值个数是否相等
        if (a.length !== b.length) {
            return false;
        } else {
            //比对参数值是否全等
            for (let i = 0, len = a.length; i < len; i++) {
                if (a[i] !== b[i]) {
                    return false
                }
            }
            return true;
        }
    } else {
        throw '参数必须都为数组';
    }
}
/*第三题*/
//深匹配两个对象是否相等
function equalObject1(a, b) {
    //核实参数是否是对象
    if (typeof a === 'object' && typeof b === 'object') {
        let aArr = Object.keys(a), bArr = Object.keys(b);
        //比对参数属性个数是否相等
        if (aArr.length !== bArr.length) {
            return false;
        } else {
            //比对参数属性值是否全等
            for (let i = 0, len = aArr.length; i < len; i++) {
                let x = aArr[i];
                if (!equal(a[x],b[x])) {
                    return false
                }
            }
            return true;
        }
    }
}
//深匹配两个数组是否相等
function equalArray1(a,b){
    //核实参数是否是数组
    if ( a instanceof Array && b instanceof Array) {
        //比对参数值个数是否相等
        if (a.length !== b.length) {
            return false;
        } else {
            //比对参数值是否全等
            for (let i = 0, len = a.length; i < len; i++) {
                if (!equal(a[i],b[i])) {
                    return false
                }
            }
            return true;
        }
    }
}
//辅助函数判断参数类型
function judge(a){
    if(typeof a === 'object'){
        if(a instanceof Array){
            return 'array';
        }else{
            return 'object';
        }
    }else{
        return 'noobject';
    }
}
//equal函数
function equal(a,b){
    let aType = judge(a);
    let bType = judge(b)
    if(aType !== bType){
        return false;
    }
    switch(aType){
        case 'array': return equalArray1(a,b); break;
        case 'object': return equalObject1(a, b); break;
        case 'noobject': return a===b?true:false; break;
    }
}

测试用例:

var ans0 = equalObject({ a: 1, b: 2 }, { b: 2, a: 1 })
var ans1 = equalArray([1, 2], [1, 2])
var ans2 = equalArray([1, 2], [1, '2'])
var ans3 = equal({ a: [1, '2'], b: 2 }, { b: 2, a: [1, '2'] })
var ans4 = equal([1, 2, { a: 1, b: 2 }, 9], [1, 2, { b: 2, a: 1 }, 9])
var ans5 = equal([1, 2, { a: 1, b: 2 }, 9], { a: [1, '2'], b: 2 })
console.table([ans0, ans1, ans2, ans3, ans4, ans5])

1552557797

lockontan commented 5 years ago
   const toString = Object.prototype.toString

    const isArray = function (value) {
      return toString.call(value) === '[object Array]'
    }

    const isObject = function (value) {
      return toString.call(value) === '[object Object]'
    }

    const getKeys = function (value) {
      let keys = Object.keys(value).sort()
      if (isArray(value)) {
        keys = keys.map(key => parseInt(key))
      }
      return keys
    }

    const equalBaseArray = function (o1, o2) {
      if (o1.length !== o2.length) return false
      for (let i = 0; i < o1.length; i++) {
        if (o1[i] !== o2[i]) return false
      }
      return true
    }

    const equal = function (o1, o2) {
      const k1 = getKeys(o1)
      const k2 = getKeys(o2)
      if (!equalBaseArray(k1, k2)) return false
      for (let i = 0; i < k1.length; i++) {
        const v1 = o1[k1[i]]
        const v2 = o2[k2[i]]
        if (isObject(v1) || isArray(v1) && isObject(v2) || isArray(v2)) {
          if (!equal(v1, v2)) {
            return false
          }
        } else if (o1[k1[i]] !== o2[k2[i]]) {
          return false
        }
      }
      return true
    }

image

wind1996 commented 5 years ago

针对对象和数组的任意组合,仅支持基本数据类型。本函数默认NaN等于NaN

const isArray = v => Array.isArray(v);
const getType = v => Object.prototype.toString.call(v);
const isObject = v => getType(v) === '[object Object]';
const isNaN = v => Number.isNaN(v);

const equalArray = (a, b) => a.length === b.length && !a.some((item, index) => !equal(item, b[index]));

const equalObject = (a, b) => (Object.keys(a).length === Object.keys(b).length) &&
    !Object.entries(a).some(([key, value]) => !equal(value, b[key]));

const equal = (a, b) => {
    if (getType(a) !== getType(b)) {
        return false;
    }
    if (isArray(a)) {
        return equalArray(a, b);
    }
    if (isObject(a)) {
        return equalObject(a, b);
    }
    if (isNaN(a) && isNaN(b)) {
        return true
    }
    return a === b;
};
whrice commented 5 years ago
//已知纯对象
function equalObject(obj1,obj2){
/*对象长度一般无法使用.length获取*/
    if(!(isNaN(obj1.length)&&isNaN(obj2.length))){
      return false;
}
   if(Object.keys(obj1).length==Object.keys(obj2).length){
        if(Object.keys(obj1).length ==0){
           return false;
      };
       for(key in obj1){
           if(obj2.hasOwnProperty(key)){
              if(obj1[key]==obj2[key]){
              continue;
               }
            else return false;
           }
       }
       return true;   
   }
 return false;
  }
//已知数组 并且考虑数组中有对象的情况
function equalArray(arr1,arr2){
   if(arr1.length!=arr2.length){
       return false;
   }
   for(var i=0;i<arr1.length;i++){
      if(arr1[i]===arr2[i]){
        continue;
      }
      else{
        if(typeof arr1[i]=="object"&&typeof arr2[i]=="object"){
                    if(arr1[i]==&&arr[2]){
                      }
         if(equalObject(arr1[i],arr2[i])){
           continue;
         }
        }
         return false;
      }
   }
   return true;
}  
//判断内容形态一致
function equal(obj1,obj2){
//判断两个变量是否是对象类型
   if(typeof obj1=== 'object' &&typeof obj2=== 'object'){
       //数组
       if(!isNaN(obj1.length) && !isNaN(obj2.length)){
       return equalArray(obj1,obj2);
        }
       //对象
       if(isNaN(obj1.length)&&isNaN(obj2.length)){
           if(Object.keys(obj1).length==Object.keys(obj2).length){
               for(key in obj1){
                   if(obj2.hasOwnProperty(key)){
                       if(typeof obj1[key]=="object"){
                           if (!equalArray(obj1[key],obj2[key])){
                               return false;
                           };
                       }
                       obj1[key]==obj2[key];
                   }
                   else{
                       return false;
                   }
               }
                return true;   
           }
       else return false;
       }
   }
return obj1===obj2;
}
littleKnave commented 5 years ago

1.第一题需要考虑:1.对象键值长度,2.两个对象相同键对应的数值,3.如何遍历

function equalObject(obj1 = {}, obj2 = {}) {
  const obj1Keys = Object.keys(obj1);
  const obj2Keys = Object.keys(obj2);
  // 如果键值对长度不相等,返回false
  if (obj1Keys.length !== obj2Keys.length) {
    return false;
  }
  let isEqual = true;
  obj1Keys.forEach((item) => {
    // 相同键的值判断
    if (obj1[item] !== obj2[item]) {
      isEqual = false;
    }
  })
  return isEqual;
}

2.第二题需要考虑:1.两个数组长度,2.两个数组值是否有值对应的上,3.考虑重复问题,如[1,1,2,3]和[1,2,2,3]的情况,所以需要有个计数器,记录数组内值出现次数,4.如何遍历

function equalArray(arr1 = [], arr2 = []) {
  // 如果数组长度不一致,返回false
  if (arr1.length !== arr2.length) {
    return false;
  }
  // 使用map保存数组原生数据
  const arrMap = new Map();
  // 长度一致,选择任意数组转成对象格式,重复对象值+1
  arr1.forEach((arr1Item) => {
    if (arrMap.has(arr1Item)) {
      let num = arrMap.get(arr1Item);
      arrMap.set(arr1Item, ++num);
    } else {
      arrMap.set(arr1Item, 1);
    }
  });
  for (let arr2Item of arr2) {
    if (!(arrMap.has(arr2Item))) {
      // arr2多余项未匹配
      return false;
    }
    let num = arrMap.get(arr2Item);
    arrMap.set(arr2Item, --num)
  }
  for (let i of arrMap.values()) {
    if (i !== 0) {
      // arr1多余项未匹配
      return false;
    }
  }
  return true;
}

3.第三题需要考虑前两题的情况,题目又说只要形态内容一致,就算一致。那要考虑{} === {} = true的情况,因为没时间解决这种情况。只是把上面两个方法合并起来做了个大概的功能

function equal(arg1, arg2) {
  if (typeof arg1 !== 'object' || arg1 === null) {
    // 基本类型直接比对
    return arg1 === arg2;
  }
  // 数组比对
  if (Array.isArray(arg1) && Array.isArray(arg2)) {
    if (arg1.length !== arg2.length) {
      return false;
    }
    // 使用map保存数组原生数据
    const arrMap = new Map();
    // 长度一致,选择任意数组转成对象格式,重复对象值+1
    arg1.forEach((arg1Item) => {
      if (arrMap.has(arg1Item)) {
        let num = arrMap.get(arg1Item);
        arrMap.set(arg1Item, ++num);
      } else {
        arrMap.set(arg1Item, 1);
      }
    });
    for (let arg2Item of arg2) {
      if (!(arrMap.has(arg2Item))) {
        // 基本项未匹配
        if (typeof arg2Item !== 'object' || arg2Item === null) {
          // arg2多余项未匹配
          return false;
        }
        let isArrEqual = false;
        for (let arg1Item of arg1) {
          if (equal(arg1Item, arg2Item)) {
            let num = arrMap.get(arg1Item);
            arrMap.set(arg1Item, --num)
            isArrEqual = true;
          }
        }
        // 未匹配项
        if (!isArrEqual) {
          return false;
        } else {
        }
        continue;
      }
      let num = arrMap.get(arg2Item);
      arrMap.set(arg2Item, --num)
    }
    for (let i of arrMap.values()) {
      if (i !== 0) {
        // arr1多余项未匹配
        return false;
      }
    }
    return true;
  }
  const obj1Keys = Object.keys(arg1);
  const obj2Keys = Object.keys(arg2);
  // 如果键值对长度不相等,返回false
  if (obj1Keys.length !== obj2Keys.length) {
    return false;
  }
  let isEqual = true;
  obj1Keys.forEach((item) => {
    // 相同键的值判断
    if (arg1[item] !== arg2[item]) {
      if (typeof arg1[item] !== 'object' || arg1[item] === null) {
        isEqual = false;
      } else {
        let isObjEqual = false;
        if (equal(arg1[item], arg2[item])) {
          isObjEqual = true;
        }
        isEqual = isObjEqual;
      }
    }
  })
  return isEqual;
};
notzheng commented 5 years ago
function equalObject(obj1, obj2) {
    const aKeys = Object.getOwnPropertyNames(obj1)
    return aKeys.length === Object.getOwnPropertyNames(obj2).length
        && aKeys.every(k =>
            // 留意 {a:1, b:2, c:undefined} {a:1,b:2,d:undefined }
            // b.hasOwnProperty(k) && Object.is(a[k], b[k])
            // 出题者注:上面写作了,纠正下
            obj2.hasOwnProperty(k) && Object.is(obj1[k], obj2[k])
        )
}

function equalArray(arr1, arr2) {
    return arr1.length === arr2.length && arr1.every((item, idx) => Object.is(item, arr2[idx]))
}

function equal(a, b) {
    console.log(a,b)
    const typeA = typeof a;
    const typeB = typeof b;
    // 类型不等
    if (typeA !== typeB){ return false}
    // 都是数组
    if (Array.isArray(a) && Array.isArray(b)) {
        return a.length === b.length && a.every((item, idx) => equal(item, b[idx]))
    }

    if (typeA === typeB && typeA === 'object') {
        // 不是 null 就是俩对象
        return Object.is(a, b) ||
            (Object.getOwnPropertyNames(a).length === Object.getOwnPropertyNames(b).length
                && Object.getOwnPropertyNames(a).every(
                    k => b.hasOwnProperty(k) && equal(a[k], b[k])
                )
            )
    }

    return Object.is(a,b)
}
RichardDFang commented 5 years ago

// zhangxinxu: objectA.keys需要做合法性判断

        // 第一题
        function equalObject (objectA, objectB) {
            if (!isObject(objectA)) {
                throw new TypeError(`${objectA} is not object`);
                return ;
            }

            if (!isObject(objectB)) {
                throw new TypeError(`${objectB} is not object`);
                return ;
            }

            return fullEqualObject(objectA, objectB);
        }

        // 第二题
        function equalArray (arrayA, arrayB) {
            if (!Array.isArray(arrayA)) {
                throw new TypeError(`${arrayA} is not array`);
                return ;
            }

            if (!Array.isArray(arrayB)) {
                throw new TypeError(`${arrayB} is not array`);
                return ;
            }

            if (arrayA.length !== arrayB.length) {
                return false;
            }

            return arrayA.every(function(val, index) {
                return val === arrayB[index];
            })
        }

        // 第三题
        function equal (objectA, objectB) {
            if (isAllArray(objectA, objectB)) {
                if (objectA.length !== objectB.length) {
                    return false;
                }

                return objectA.every(function(val, index) {
                    let objectBVal = objectB[index];
                    if (isAllArray(val, objectBVal) || isAllNotArrayObject(val, objectBVal)) {
                        return equal(val, objectBVal);
                    } else {
                        return val === objectBVal;
                    }
                })

            } else if (isAllNotArrayObject(objectA, objectB)) {
                if (objectA.keys().length !== objectB.keys().length) {
                    return false;
                }

                for (let i in objectA) {
                    let objectBVal = objectB[i];
                    let objectAVal = objectA[i];
                    if (isAllArray(objectAVal, objectBVal) || isAllNotArrayObject(objectAVal, objectBVal)) {
                        if (!equal(objectAVal, objectBVal)) {
                            return false;
                        }
                        continue;
                    } else if (objectAVal !== objectBVal) {
                        return false;
                    }
                }

                return true;
            }

            return false;
        }
        function fullEqualObject (objectA, objectB) {
            if (objectA.keys().length !== objectB.keys().length) {
                return false;
            }

            for (let i in objectA) {
                if (isObject(objectA[i]) && isObject(objectB[i])) {
                    if (!fullEqualObject(objectA[i], objectB[i])) {
                        return false;
                    }
                    continue;
                }

                if (objectA[i] !== objectB[i]) {
                    return false;
                }
            }
            return true;
        }

        function isAllArray (objectA, objectB) {
            return Array.isArray(objectA) && Array.isArray(objectB);
        }

        function isAllNotArrayObject (objectA, objectB) {
            return (!Array.isArray(objectA) && isObject(objectA)) && (!Array.isArray(objectB) && isObject(objectB));
        }

        function isObject (object) {
            return Object.prototype.toString.call(object).slice(8, -1).toLowerCase() === 'object';
        }
MissHoya commented 5 years ago

首次打卡

function getType(obj) {
    return Object.prototype.toString.call(obj);
}
function compare(type, item1, item2) {
    return (type === '[object Array]' && equalArray(item1, item2)) ||
        (type === '[object Object]' && equalObject(item1, item2)) ||
        item1 === item2;
}

/* 第一题 */
function equalObject(obj1, obj2) {
    var result = true;
    var keys1 = Object.keys(obj1);
    var keys2 = Object.keys(obj2);
    if (keys1.length !== keys2.length)
        return false;
    for (var i = 0; i < keys1.length; i++) {
        var key = keys1[i];
        if (!obj2.hasOwnProperty(key)) {
            result = false;
            break;
        }
        var type1 = getType(obj1[key]);
        var type2 = getType(obj2[key]);
        if (type1 !== type2 || !compare(type1, obj1[key], obj2[key])) {
            result = false;
            break;
        }
    }
    return result;
}
/* 第二题 */
function equalArray(arr1, arr2) {
    var length1 = arr1.length;
    var length2 = arr2.length;
    var result = true;
    if (length1 !== length2)
        return false;
    for (var i = 0; i < length1; i++) {
        var item1 = arr1[i];
        var type1 = getType(item1);
        var item2 = arr2[i];
        var type2 = getType(item2);
        if (type1 !== type2 || !compare(type1, item1, item2)) {
            result = false;
            break;
        }
    }
    return result;
}
/* 第三题 */
function equal(item1, item2) {
    var type1 = getType(item1);
    var type2 = getType(item2);
    if (type1 !== type2)
        return false;
    var result = true;
    if (type1 !== type2 || !compare(type1, item1, item2)) {
        result = false;
    }
    return result;
}
zhangxinxu commented 5 years ago

要点总结:

  1. JSON.stringify有问题
  2. 题意没看清,题目1和题目2不等同与题目3
  3. 忘记先做长度判断,忘记先做类型判断
  4. 对比数组每一项是否相等可以使用every方法
  5. NaN判断可以使用Object.is()
  6. 可以看看NeilC1991的实现,我觉得挺好的(经反馈:还需加上类型判断),XboxYan、ylfeng250、DFLovingWM的实现通过了新的测试用例
  7. 补充:可以先判断是否完全相等
zhangxinxu commented 5 years ago

测试地址:https://www.zhangxinxu.com/study/201903/qunit.html

Seasonley commented 5 years ago

抱歉没看直播,不过我可以答个跟你们不一样的。 @zhangxinxu 张大大equalArray测试用例可以加个预期结果是true的~

var isObj =o=>Object.prototype.toString.call(o)==='[object Object]'
var isArray =o=>Object.prototype.toString.call(o)==='[object Array]'
var sameLen=(a,b)=>Object.keys(a).length===Object.keys(b).length
var keyEq=(a,b)=>key=>a[key]===b[key]||Object.is(a[key],b[key])
var keysNotBase=a=>Object.keys(a).filter(k=>isObj(a[k])||isArray(a[k]))

var equalObject=(a,b)=>a===b||Object.is(a,b)||
[a,b].every(isObj) && sameLen(a,b)
&&Object.keys(a).every(keyEq(a,b))

var equalArray=(a,b)=>
[a,b].every(isArray) && sameLen(a,b)
&&Object.keys(a).every(keyEq(a,b))

var equal=(a,b)=>equalObject(a,b)||equalArray(a,b)||
sameLen(a,b)&&!!keysNotBase(a).length
&&keysNotBase(a).every(k=>equal(a[k],b[k]))
Fatty-Shu commented 5 years ago

之前就做了的,忘记提交了。看了下注意点,漏了NaN的相等判断。

// 题一
function equalObject(a, b){
    if (!a || !b) {return false}
    let props = Object.getOwnPropertyNames(a)
    if (props.length === Object.getOwnPropertyNames(b).length) {
        for(let i = 0, len = props.length; i<len; i++) {
            if( a[props[i]] !== b[props[i]]) {
                return false
            }
        }
        return true
    }
    return false
}
// 题二
function equalArray(a, b){
    if (!a || !b) {return false}
    if (a.length === b.length) {
        for(let i = 0, len = a.length; i<len; i++) {
            if( a[i] !== b[i]) {
                return false
            }
        }
        return true
    }
    return false
}
// 题三
function getClass(v) {
    return Object.prototype.toString.call(v).slice(8, -1)
}
function equal(a, b) {
    if (getClass(a) !== getClass(b)) return false
    if (getClass(a) === 'Array' && a.length !== b.length) {
        return false
    }
    if (getClass(a) === 'Array') {
        for (let i = 0, len = a.length; i < len; i++) {
            if (!equal(a[i], b[i])) { return false }
        }
        return true
    }
    if (getClass(a) === 'Object') {
        let props = Object.getOwnPropertyNames(a)
        if (props.length === Object.getOwnPropertyNames(b).length) {
            for(let i = 0, len = props.length; i<len; i++) {
                if(!equal(a[props[i]], b[props[i]])) {
                    return false
                }
            }
            return true
        }
        return false
    }
    return a === b
}
VarHug commented 5 years ago
/**
 * DFS判断是否相等
 * @param {Object} obj1
 * @param {Object} obj2
 * @param {boolean} [ref=true] 是否需要判断引用类型相等
 * @returns {boolean}
 */
function _equal(obj1, obj2, ref=true) {
  let stack = []
  stack.push(obj1, obj2)
  while (stack.length) {
    let item1 = stack.shift()
    let item2 = stack.shift()
    let keys = Object.keys(item1)
    let isEqual = keys.every((key) => {
      if (item1[key] instanceof Object) {  // 忽略函数
        stack.push(item1[key], item2[key])
        if (ref) {
          return true
        } else {
          return false
        }
      } else {
        return item1[key] === item2[key]
      }
    })
    if (!isEqual) {
      return false
    }
  }
  return true
}

/**
 * 判断两个对象是否原生相等
 * @param {Object} obj1
 * @param {Object} obj2
 * @returns {boolean} 
 */
function equalObject(obj1, obj2) {
  let type1 = Object.prototype.toString.call(obj1)
  let type2 = Object.prototype.toString.call(obj2)
  if (type1 !== type2) {
    return false
  }
  let len1 = Object.keys(obj1).length
  let len2 = Object.keys(obj2).length
  if (len1 !== len2) {
    return false
  }
  return _equal(obj1, obj2, false)
}

/**
 * 判断两个数组是否原生相等
 * @param {Array} arr1
 * @param {Array} arr2
 * @returns {boolean} 
 */
function equalArray(arr1, arr2) {
  if (arr1.length !== arr2.length) {
    return false
  }
  return _equal(arr1, arr2, false)
}

/**
 * 判断两个对象是否相等
 * @param {Object} obj1
 * @param {Object} obj2
 * @returns {boolean}
 */
function equal(obj1, obj2) {
  let type1 = Object.prototype.toString.call(obj1)
  let type2 = Object.prototype.toString.call(obj2)
  if (type1 !== type2) {
    return false
  }
  let len1 = Object.keys(obj1).length
  let len2 = Object.keys(obj2).length
  if (len1 !== len2) {
    return false
  }
  return _equal(obj1, obj2, true)
}
jsweber commented 5 years ago
function equalObject(a, b){
    if (!isObject(a) || !isObject(b)) return false
    for (let key in a){
        if (a.hasOwnProperty(key)){
            if (!b[key]) return false
            if (b[key] !== a[key]) return false
        }
    }
    for (let key in b){
        if (b.hasOwnProperty(key)){
            if (!a[key]) return false
            if (b[key] !== a[key]) return false
        }
    }
    return true
}

function equalArray(a, b){
    if (Array.isArray(a) && Array.isArray(b) && (a.length === b.length)){
        for (let i = 0; i < a.length; i++){
            if (a[i] !== b[i]) return false
        }
        return true
    }

    return false
}

function equal(a, b){
    //首先判断两个参数是否类型一致,即都是数组或者都是原生object
    if ( (Array.isArray(a) && Array.isArray(b)) || (isObject(a) && isObject(b)) ){
        let keys1 = Object.keys(a)
        let keys2 = Object.keys(b)
        //如果两者自身key的长度不一致就直接false
        if (keys1.length !== keys2.length) return false

        for (let i = 0; i < keys1.length; i++){
            let key = keys1[i]
            //因为上面已经比对过key的长度,所以这里可以直接这样判断,a中的key如果b没有就是false
            if (!b[key]) return false
            let val1 = a[key]
            let val2 = b[key]
            //两者都不是基本类型就进入递归比较,进入这里要么是都是数组,要么都是对象,所以只要不是基本类型就可以了
            if (!isPrimary(val1) && !isPrimary(val2)){
                if (!equal(val1, val2)) return false
            }else{
                if (val1 !== val2) return false
            }
        }
        return true
    }else 
        return false
}

function isObject(o){
    return typeof o === 'object' && !Array.isArray(o)
}

function isPrimary(n){
    return typeof n === 'number' || typeof n === 'boolean' || typeof n === 'string'
}

//test
console.log(equal({a:1, b:['1', {'abc': 1}]}, {a: 1, b:['1', {'abc': 1}]}))
console.log(equal([1,{a: 10, arr: [12,'34'], hello: 'world'}], [1, {hello: 'world', a: 10, arr: [12,34]}]))
>true
>false
jumodada commented 5 years ago
function _typeof(item) {
    return Object.prototype.toString.call(item).slice(8, this.length - 1)
}
//1
function equalObject(obj,compareObj){
    if(_typeof(obj)!==_typeof(compareObj))return false
    if(Object.keys(obj).length!==Object.keys(compareObj).length)return false
   return  Object.keys(obj).every(item=>{
        return obj[item]===compareObj[item]
    })
}

// 2
function equalArray(arr,compareArr) {
    let judge = true
    if(arr.length!==compareArr.length)return false
    arr.forEach((item,index)=>{
        if(item!==compareArr[index])judge =false
    })
    return judge
}
//3

function equal(obj,compareObj) {
    if(_typeof(obj)!==_typeof(compareObj))return false
    if(Object.keys(obj).length!==Object.keys(compareObj).length)return false
        let judge = true
    Object.keys(obj).forEach(item=>{
        if(typeof obj[item]==='object'){
            if(!equal(obj[item],compareObj[item]))judge=false
        }else{
            if(obj[item]!==compareObj[item])judge =false
        }
    })
    return judge
}
//全部通过29期单元测试