原文出处:Object Equality in JavaScript
相称是JavaScript中早先最让人疑心的部份。==
和===
的比较、强迫范例的递次等等,都使得这个题目变得复杂。本日,我们会聚焦另一个方面:object相称是怎样完成的。
你或许以为,假如两个object有雷同的属性而且它们多有的属性值都雷同,那末这两个object应该是相称的。我们来看看是不是如我们所料:
var jangoFett = {
occupation: "Bounty Hunter",
genetics: "superb"
};
var bobaFett = {
occupation: "Bounty Hunter",
genetics: "superb"
};
// Outputs: false
console.log(bobaFett === jangoFett);
bobaFett
和jangoFett
的属性完全雷同,然则两个object并不以为是相称的。岂非是我们运用恒等运算符的缘由?我们来考证下:
// Outputs: false
console.log(bobaFett == jangoFett);
我们如许做,是因为JavaScript内部其实有两套差别的计划来考证相称(译者加:ecma范例中定义的[The Strict Equality Comparison Algorithm
](http://www.ecma-international…)。像字符串以及数值这类基础范例是依据它们的值举行比较的;但像数组、日期以及简朴对象这类object是依据它们的援用举行推断的。依据援用的推断会搜检所给的object是不是指向内存中的雷同地点。下面这个例子会论述JavaScript中相称运算符的完成道理:
var jangoFett = {
occupation: "Bounty Hunter",
genetics: "superb"
};
var bobaFett = {
occupation: "Bounty Hunter",
genetics: "superb"
};
var callMeJango = jangoFett;
// Outputs: false
console.log(bobaFett === jangoFett);
// Outputs: true
console.log(callMeJango === jangoFett);
一方面讲,jangoFett
和bobaFett
这两个变量援用自两个具有完全雷同属性的object,但确实为两个差别的实例;另一方面,jangoFett
和callMeJango
指向雷同的实例。
因而,当你想要考证对象相称时,你须要清晰你是想要怎样的相称。假如你是想考证两个实例是不是完完全全雷同,你可以运用JavaScript内置的相称运算符;抑或你是想考证两个实例具有“雷同的值”,如许的话,你可以须要多做些事情。
以下是磨练object“值相称”的一种基础完成:
function isEquivalent(a, b) {
// Create arrays of property names
var aProps = Object.getOwnPropertyNames(a);
var bProps = Object.getOwnPropertyNames(b);
// If number of properties is different,
// objects are not equivalent
if (aProps.length != bProps.length) {
return false;
}
for (var i = 0; i < aProps.length; i++) {
var propName = aProps[i];
// If values of same property are not equal,
// objects are not equivalent
if (a[propName] !== b[propName]) {
return false;
}
}
// If we made it this far, objects
// are considered equivalent
return true;
}
// Outputs: true
console.log(isEquivalent(bobaFett, jangoFett));
如你所见,想要考证object实例“值相称”,我们必需去遍历object中每一个属性,看其是不是相称。假如我们把上面完成的这个简朴计划应用在我们的例子中,许多状况都是还没有处置惩罚的。比方:
- 假如某个属性是一个object
- 假如某个属性值时
NaN
(JavaScript中唯一一个本身不相称本身的值) - 假如
a
有个属性的值为undefined
,而b
中没有这个属性(因而都等同于undefined
)
想要一个磨练object实例“值相称”的硬朗的要领,最好是运用一个涵盖种种边境状况的、经由周全测试的库。Underscore和Lo-Dash这两个库中的_.isEqual
要领对处置惩罚object深度比较举行了很好的完成。你可以如许运用它们:
// Outputs: true
console.log(_.isEqual(bobaFett, jangoFett));
愿望这个JavaScript的小知识点可以协助你更好地明白object实例相称的完成道理。