quiz
quiz copied to clipboard
JS基础测试第29期
本期为JS基础测试,题目如下:
前两小题只需要考虑值是否原生相等即可。第3题难度加大,形式一样的数组值或者对象值也认为是相等的。
补充:数组 [1, 2] 和 [2, 1] 是不等的。
大家提交回答的时候,注意缩进距离,起始位置从左边缘开始;另外,github自带代码高亮,所以请使用下面示意的格式。
```js // 你的JS代码写在这里 ```
参与答题即得2积分,第1位答题者额外1积分,精妙实现者额外1积分。
在网上找了一下解题思路,找到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
}
- every() 方法测试数组的所有元素是否都通过了指定函数的测试。
- 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
}
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));
// 第一题
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;
}
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;
}
}
在网上找了一下解题思路,找到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
}