There are lots of other traps to be aware of:
http://philrathe.com/articles/equiv -- specifically the "traps to be aware of section". Most of these we are already aware of. The RegExp one and the Boxed types are particulrly interesting. Flusspferd is going to be using this implementation for deepEqual.
// Consider those problems. All statements return true.
// typeof operator
typeof {} === "object";
typeof [] === "object"; // Oops! It isn't "array"
typeof function(){} === "function";
typeof "myString" === "string";
typeof 5 === "number";
typeof true === "boolean";
typeof null === "object"; // Oops! It isn't null
typeof undefined === "undefined";
// Date
var d1 = new Date();
var d2 = new Date();
d1.setMilliseconds(0);
d2.setMilliseconds(0);
d1.valueOf() === d2.valueOf(); // Yes they are the same date
d1 !== d2; // Oops!
// RegExp
var a = /./;
a instanceof Object; // Oops
a instanceof RegExp;
typeof a === "function"; // Oops, false in IE and Opera, true in FF and Safari ("object")
// object literal
var o1 = {};
var o2 = {
foo: undefined
};
o1["foo"] === o2["foo"]; // Oops!
// Number
1/0 !== 1/0; // Oops! NaN doesn't equals itself!
// Well it may be ok, or not, it still confusing
// == operator
"1" == true; // Oops! use === not ==
// === operator
new Number(4) !== 4; // Oops!
new String('foo') !== 'foo'; // Oops!
new Boolean(true) !== true; // Oops! ...
// Must use the == operator or valueOf() instead
// being careful about comparing same type together
Also when are functions equal? should they be checked when they are properties of an object?
The sample implementation from narwhal also suffers from infinite recursion with:
var b1 = ByteString([1]),
b2 = ByteString([2]);
assert.deepEqual(b1,b2);
due to the Binary (B and D) spec that says [[Get]] should return another ByteString. This is one of the reasons why I don't like that behvaiour.
-ash