javascript是不能用 '=='或'==='操作符直接比较两个数组是否相等的
var a = [1,2,3,4,5];
var b = a.slice();
console.log(a); // [1,2,3,4,5]
console.log(b); // [1,2,3,4,5]
console.log(a === b); // false
console.log(a == b); // false
console.log([] == []); // false
console.log( [] === []); // false
为什么都输出false呢?先弄清楚以下几点:
javascript包括两个不同类型的值:基本数据类型和引用数据类型。
基本数据类型指的是简单的数据段,引用数据类型指的是有多个值构成的对象。
常见的基本数据类型:Number、String 、Boolean、Null和Undefined。
var a = 10;
var b = a;
b = 20;
console.log(a); // 10
上面b获取的是a值的一份拷贝,虽然两个变量的值相等,但是两个变量保存了两个不同的基本数据类型值。b只是保存了a赋值的一个副本,所以,b的改变,对a没有影响。
引用类型数据:也就是对象类型Object type,比如:Object、Array、Function、Data等。javascript的引用数据类型是保存在堆内存中的对象。
讲到这里应该理解为什么输出的是false了:因为数组是兑现,==或===操作符只能比较两个对象是否是同一个实例,也就是是否是同一个对象引用。目前JavaScript没有内置的操作符判断对象的内容是否相同。
那么该如何去判断数组是否相等呢?
有一种做法是将数组转换成字符串:
JSON.stringify(a1) === JSON.stringify(a2)
或
a1.toString() === a2.toString();
请不要使用这种方法!!!
这种方法在某些情况下是可行的,当两个数组的元素顺序相同且元素都可以转换成字符串的情况下确实可行。
这样的代码存有隐患,比如数字被转换成字符串,数字“1”和字符串“1”会被认为相等,可能造成调试困难,不推荐使用。
function isEqual (a, b) {
const classNameA = toString.call(a)
const classNameB = toString.call(b)
// 如果数据类型不相等,则返回false
if (classNameA !== classNameB) {
return false
} else {
// 如果数据类型相等,再根据不同数据类型分别判断
if (classNameA === '[object Object]') {
for (let key in a) {
if (!isEqual(a[key], b[key])) return false
}
for (let key in b) {
if (!isEqual(a[key], b[key])) return false
}
return true
} else if (classNameA === '[object Array]') {
if (a.length !== b.length) {
return false
} else {
for (let i = 0, len = a.length; i < len; i++) {
if (!isEqual(a[i], b[i])) return false
}
return true
}
} else if (classNameA === '[object Function]') {
return a.toString() === b.toString()
} else {
return Object.is(a, b)
}
}
}
const a = {
arr: [1, true, {a: 6, arr: [9, 0, 6, [5, 9]]}],
d: 0,
obj: { d: 9, arr: [5000]},
e: ()=>{},
f: [0]
}
const b = {
arr: [1, true, {a: 6, arr: [9, 0, 6, [5, 9]]}],
d: 0,
obj: { d: 9, arr: [5000]},
e: ()=>{},
f: [0]
}
console.log(isEqual(a, b))