-
-
Save tarao/5182203 to your computer and use it in GitHub Desktop.
// http://blog.livedoor.jp/dankogai/archives/51859373.html | |
var x = { a: 1, b: 2, c: 3 }; | |
var y = { a: 1, b: 2, c: 3, d: 4 }; | |
var z = {a: 1, b: 2, c: 3 }; | |
var w = {a: 1, b: 2, c: 3, d: 4 }; | |
x.b = w; | |
y.b = x; | |
z.b = y; | |
w.b = x; | |
Object.equals(x, z); // false | |
Object.equals(z, x); // true | |
Object.equals(y, w); // true | |
Object.equals(w, y); // false | |
/* How to check deep equality precisely? | |
cf. "Deep equality revisited" | |
S. Abiteboul and J. Van den Bussche | |
Deductive and Object-Oriented Databases, Lecture Notes in Computer Science, vol 1013, pages 213-228. Springer, 1995. | |
*/ |
I thought that Object.equals
is a structural equivalence for
values and a reference is not a value. In this case, it should
examine the structures of x
and z
as values of infinite trees
and should not be sensitive to self-reference since the "values"
do not contain references by definition. (I'm talking about the
formal definition of values for a particular structural
equivalence relation, not the implementation of values in
JavaScript.)
I'm not disagreeing with your opinion that the current
implementation of Object.equals
somehow makes sense, as long as
its formal definition is well-defined. I understand that the
formal definition is different from what I thought.
Unfortunately, I found that the current implementation of
Object.equals
is not well-defined, at least as an equivalence
relation. The (updated) example shows that Object.equals
is not
symmetric. I think the name equals
implies that it is an
equivalence relation (not necessarily a structural equivalence), i.e.,
a relation which is reflexive, symmetric and transitive. So I have to
conclude that Object.equals
is not well-defined.
// I think this extreme case is forgivable since even uneval() of firefox was fooled.
// (though it was souped down since Firefox 12)
// add the snippet below and here is what I got in firefox:
try {
console.log(uneval(x))
console.log(uneval(z));
}catch(e){
console.log('uneval() is missing');
}
// ({a:1, b:{a:1, b:{}, c:3, d:4}, c:3})
// ({a:1, b:{a:1, b:{a:1, b:{a:1, b:{}, c:3, d:4}, c:3}, c:3, d:4}, c:3})
// as the result suggests, x and z differ in "when", not "where" it bumps into self-reference.
// it should be documented, however.