目前我正在关注一本书并且非常困惑,并且多次尝试了解以下代码。我的第一个困惑实际上是在解决比较两个对象 a 和 b 的问题。
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;
}
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
答案 0 :(得分:3)
function deepEqual(a, b) {
if (a === b) return true;
首先,我们正在检查a
和b
是否严格相等(意思是,“指的是完全相同的东西”) 。大多数事情,如字符串和数字,如果相等,都会通过这个测试;对象是例外,因为两个“相同”的对象可能不一定是相同的对象(它们看起来可能相同)。
if (a == null || typeof a != "object" ||
b == null || typeof b != "object")
return false;
然后我们说如果两者中的任何一个不是对象,并且它们没有通过最后一次测试,那么它们就不能相同。同样,对象在这里是例外,因此剩下的代码将处理a
和b
都是对象的情况。
var propsInA = 0, propsInB = 0;
for (var prop in a)
propsInA += 1;
此代码只计算a
的属性数。
for (var prop in b) {
propsInB += 1;
if (!(prop in a) || !deepEqual(a[prop], b[prop]))
return false;
}
此代码获取b
中的每个属性,并检查a
是否包含具有相同值的相同属性。如果a
没有b
具有的属性,或者它们不同,则两个对象不能相等。
return propsInA == propsInB;
}
最后,如果a
和b
没有相同数量的属性,那么它们就不能相等。但是,如果它们具有相同数量的属性,则a
和b
必须相同,因为a
具有b
具有的所有属性,和只有那些。
答案 1 :(得分:1)
我将引导您完成它。
if (a === b) return true;
我们检查这些是否相同,我们稍后会再回到这里。
if (a == null || typeof a != "object" ||
b == null || typeof b != "object")
return false;
我们检查是否定义了这些东西中的一个或两个。我们也会回到这里。
记住前两个片段,在我们递归调用函数之前,它们不会发挥作用。
var propsInA = 0, propsInB = 0;
这些将用于跟踪对象A和B中的属性数量
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中的所有属性(如果你不熟悉的话,在语法中查找...),并且每个属性都会增加变量propsInA。
第二个循环对B做同样的事情,但这里变得更加复杂。首先,它检查A中是否存在该属性,或者如果deepequal返回true。这是我们检查的前两个片段发挥作用的地方。如果我们提供的属性相同,则此处使用的第一个片段返回true。第二个片段说"如果我们通过属性而不是函数,请停在这里"。这很重要,因为如果它的初始调用,这个函数只需要在这里继续。所有递归调用只需要使用第一部分。如果这两个中的任何一个返回false,我们将false返回到初始调用,因为我们知道A和B之间存在差异。
return propsInA == propsInB;
我们无法在这里回归,因为我们实际上并不知道B中是否有更少的属性。即使其他一切看起来都是一样的,我们也不能假设他们有相同数量的属性。作为最终检查,这确保了如果A中的属性数量等于B中的数量,我们将仅返回true
请随时让我进一步解释。
答案 2 :(得分:0)
关于此功能
true
。typeof a! = "object"
- 检查参数(a和b)的类型是否为对象,如果其中一个不是对象,则函数将以返回false
结束。propsInA
因此,对于a和propsInB
为b。propsInA
和propsInB
之间进行比较,如果它们相同,则函数将以返回true
结束,否则将返回false
。答案 3 :(得分:0)
您的算法的行为如下:
如果a
和b
被视为严格相等,请返回true
a
和b
被视为严格相等:
NaN
+0
和-0
(或反之亦然)这是使用严格相等比较(===
)运算符完成的。
如果a
或b
或两者都不被视为对象,请返回false
o
不被视为对象:
o
是原始值o
属于Object类型,但有一个内部[[Call]]方法。也就是说,是一个可调用的对象,例如函数或HTML <object>
元素。o
是一个不可调用的非标准异域对象,其typeof
运算符返回的实现定义与"object
&#34;`不同。这是使用typeof
运算符完成的,该运算符返回一个包含值类型的字符串,但null
和对象除外。由于typeof null === "object"
,a == null
已被检查。
如果a
和b
具有不同数量的可枚举属性(考虑自有属性和继承属性),请返回false
。
这由propsInA
和propsInB
计算。
如果b
具有可枚举(自有或继承)属性但a
没有(不可枚举或可枚举,拥有或继承),则不一定相同具有相同名称的b
)属性,返回false
。
这是迭代for (var prop in b)
并检查prop in a
。
如果b
具有可枚举(自有或继承)属性,deepEqual
算法的值与a
中相同属性的值不同,则返回{ {1}}。
这是迭代false
并检查for (var prop in b)
。
否则,请返回deepEqual(a[prop], b[prop])
。
我认为这不是一个好的算法。例如,它认为true
,{}
和Object.prototype
都是平等的,但我不会这样说。