免责声明:我是JS的初学者
我正在阅读Eloquent Javascript,其中一个练习就是对JS中的对象进行深入比较。
有些对象定义如下:
var obj = {here: {is: "an"}, object: 2};
你应该检查他们的内容是否相等。 然后有3个测试:
console.log(deepEqual(obj, obj)); // supposed to return true
console.log(deepEqual(obj, {here: 1, object: 2})); // supposed to return false
console.log(deepEqual(obj, {here: {is: "an"}, object: 2})); // supposed to return true
这是我对深度均等方法的实现。为了简化我假设对比的对象具有相同的结构,它们在现实生活中不会,但是我的方法应该返回false(我认为)
function deepEqual(obj1,obj2)
{
console.log("========");
for(prop in obj1)
{
console.log(prop);
if (typeof(prop)=="object" && prop!=null)
{
console.log("Inspecting object ", obj1[prop],obj2[prop]);
if (!deepEqual(obj1[prop],obj2[prop]))
{
return false;
}
}
else
{
console.log("Inspecting property ",prop,'[',obj1[prop],'][',obj2[prop],']');
if (obj1[prop]!=obj2[prop])
{
console.log("Different property");
return false;
}
}
}
return true;
}
var obj = {here: {is: "an"}, object: 2};
console.log(deepEqual(obj, obj));
// → true
console.log(deepEqual(obj, {here: 1, object: 2}));
// → false
console.log(deepEqual(obj, {here: {is: "an"}, object: 2}));
// → true
它分别返回true,false和.... false!
这是输出:
========
here
Inspecting property here [ {is: "an"} ][ {is: "an"} ]
object
Inspecting property object [ 2 ][ 2 ]
true
========
here
Inspecting property here [ {is: "an"} ][ 1 ]
Different property
false
========
here
Inspecting property here [ {is: "an"} ][ {is: "an"} ]
Different property
false
有两件事我不明白:
仅供参考,本书的参考实施是:
function deepEqual(a, b) {
if (a === b) return true;
if (a == null || typeof a != "object" ||
b == null || typeof b != "object")
return false;
var propsInA = 0, propsInB = 0;
for (var prop in a)
propsInA += 1;
for (var prop in b) {
propsInB += 1;
if (!(prop in a) || !deepEqual(a[prop], b[prop]))
return false;
}
return propsInA == propsInB;
}
对我来说,第一个for循环只计算A中有多少属性? 我对第二个for循环感到困惑(对于(b中的var prop))尽管......
编辑:非常感谢答案!我不知道接受哪一个,因为两者都帮助了我很多: - /答案 0 :(得分:2)
prop
(在您的for (prop in obj)
循环中)不是值 - 它是一个键(for in
loop on MDN)。使用for in
循环时,您可以引用如下值:
for (var key in obj) {
var value = obj[key];
}
至于第二个问题:
为什么表达式" obj1 [prop]!= obj2 [prop]"的确如此, 根据日志,它们都等于:{is:" an"}?
请注意,在比较两个对象(或任何其他非原始值)时,会将它们按引用进行比较,而不是按值进行比较:
var obj1 = { name: true };
var obj2 = { name: true };
obj1 === obj2;
-> false (obj1 and obj2 are different objects)
var obj3 = { name: true };
var obj4 = obj3;
obj3 === obj4;
-> true (obj4 is basically a reference to obj3)
旁注:JavaScrpt中的一个好习惯是使用===
(严格比较)运算符而不是==
(抽象比较)。为什么?因为前一个不会隐式地将比较值转换为其他类型。 Javascript的类型转换并不那么明显,因此坚持使用更可预测的运算符会更好。使用严格的比较通常是更安全的方式来比较JS中的东西。
您可以阅读有关on MDN主题的更多信息。
答案 1 :(得分:1)
这一行错了:
if (typeof(prop)=="object" && prop!=null)
prop
是属性的键,它始终是字符串,而不是属性的值。它应该是:
if (typeof(obj1[prop])=="object" && obj1[prop]!=null)
答案 2 :(得分:0)
我有一个很好的类比可能有助于解决这个问题:
为什么表达式" obj1 [prop]!= obj2 [prop]"的确如此, 根据日志,它们都等于:{is:" an"}?
我和我的兄弟可以说我们有同一个母亲。
我和那边的那个人可以说我们有相同的车,因为我们都有一辆黑色丰田凯美瑞。
My Mother === My Brother's Mother // true, she is really the same person.
My car === Guy's car // false, looks the same but 2 different cars
obj !== {here: {is: "an"}, object: 2} // just looks the same
===是严格的平等,例如"3" === 3 // false
... AND ...
==忽略数据类型,例如"3" == 3 // true