Open zhangxinxu opened 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));
针对数组类型:首先判断长度是否相等,然后通过取交集,判断交集的长度是否和原数组长度相等。 针对对象类型:首先获取对象的 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])
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'}]))
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
})
}
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
}
/* 第一题 */
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));
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;
}
//比较数组
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
第一题:
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;
}
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])
/**
* 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]))
}
//对象比较
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;
}
}
// 比较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
}
// 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];
}
});
};
第一题:
/**
* 判断两个对象里的元素是否原生相等
* @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);
}
一般场景
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])
)
}
特殊情况值
NaN
// Object.is()RegExp
// toString()Date
// getTime()Function
// toString()enumerable prop
// Object.getOwnPropertyNames()Extend prop
// hasOwnProperty()Error
?Native code
?继承
var o1 = Object.create([]), o2 = Object.create({})
o1 instanceof Array // false
o2 instanceof Array // true
equalObj(o1, o2) // true ??
fix: 修复数组 Vs 类数组比较
//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
}
arr.every(callback) callback 被调用时传入三个参数:元素值,元素的索引,原数组。
function equalObject(obj1, obj2) {
if(types(obj1) !== "[object Object]" || types(obj2) !== "[object Object]") return false;
if (Object.keys(obj1).length !== Object.keys(obj2).length) return false;
return Object.keys(obj1).every(function (item) {
return obj1[item] === obj2[item];
})
}
function equalArray(arr1, arr2) {
if (arr1.length !== arr2.length) return false;
return arr1.every(function (item, index) {
return arr1[index] === arr2[index]
})
}
function types(params) {
return Object.prototype.toString.call(params);
}
function equal(item1, item2) {
if (types(item1) !== types(item2)) return false;
if (types(item1) === "[object Object]") {
if (Object.keys(item1).length !== Object.keys(item2).length) return false;
return Object.keys(item1).every(function (value) {
return equal(item1[value], item2[value])
})
}
if (types(item1) === "[object Array]") {
if (item1.length !== item2.length) return false;
return item1.every(function (value, index) {
return equal(item1[index], item2[index])
})
}
return item1 === item2;
}
let obj1 = {a: 1, b: 2},
obj2 = {b: 2, a: 1},
arr1 = [1, 3, 5, 7, 9],
arr2 = [1, 3, 5, 7, 9],
arr3 = [1, 2],
arr4 = [2, 1],
arr5 = [1, 2],
arr6 = ['1', '2'],
obj3 = {a: [1, '2'], b: 2},
obj4 = {b: 2, a: [1, '2']},
arr7 = [1, 2, {a: 1, b: 2}, 9],
arr8 = [1, 2, {b: 2, a: 1}, 9];
equalObject(obj1, obj2);
equalArray(arr1, arr2);
equalArray(arr3, arr4);
equalArray(arr5, arr6);
equal(obj3, obj4);
equal(arr7, arr8);
equal(obj3, arr7);
//预处理字符串化
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);
}
修改
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];
})
}
}
第一次交作业喔,张大哥会翻我牌子吗 😄
/**判断两个数组/对象是否相等(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
}
React 有个纯函数比较,代码差不多:)
一个函数搞定,函数第三个参数不传
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
}
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:[]}));
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']));
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));
// 第一题
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()
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;
}
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;
}
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]);
}
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;
}
}
在网上找了一下解题思路,找到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 遍历对象字段是不是需要去除原型链对象的字段吧
// 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
}
// 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
}
// 第一次作业,希望大大翻牌 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
}))
// 三个题目统一一个函数处理
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
}
第一题
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;
}
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;
};
注释写在代码中了。关键是第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)
}
/*第一题*/
//浅匹配两个对象是否相等
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])
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
}
针对对象和数组的任意组合,仅支持基本数据类型。本函数默认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;
};
//已知纯对象
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;
}
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;
};
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)
}
// 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';
}
首次打卡
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 张大大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]))
之前就做了的,忘记提交了。看了下注意点,漏了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
}
/**
* 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)
}
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
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期单元测试
本期为JS基础测试,题目如下:
前两小题只需要考虑值是否原生相等即可。第3题难度加大,形式一样的数组值或者对象值也认为是相等的。
补充:数组 [1, 2] 和 [2, 1] 是不等的。
大家提交回答的时候,注意缩进距离,起始位置从左边缘开始;另外,github自带代码高亮,所以请使用下面示意的格式。
参与答题即得2积分,第1位答题者额外1积分,精妙实现者额外1积分。