The two objects have the same value but are not the same object, for example if you push a new element to one the other will not get that new pushed element.
var a = [[0, 1]];
var b = [0, 1];
a[0].push(42);
alert(a[0].length); // now it's 3
alert(b.length); // still 2
Note also that the syntax [0, 1] is not representing an array object, but it's an array object "builder" that will produce a new fresh array each time it's evaluated:
function mkarr() {
return [0, 1];
}
var a = mkarr();
var b = mkarr();
a.push(42);
alert(a.length); // 3
alert(b.length); // still 2
alert(mkarr().length); // still 2 too
For numbers and strings instead equality matches because the referenced objects are immutable (i.e. you can make your variable to point to another number, but you cannot change the number itself).
Calling JSON.stringify on an object you get a string representation of the object, not the object... and the representations can indeed match equal for different objects (because they're just strings).
Note that the string representation doesn't really capture the object, and you can have substantially different objects with the same identical string representation... for example:
var a = [0, 1];
var b = [a, a];
var c = [[0, 1], [0, 1]];
alert(JSON.stringify(b) == JSON.stringify(c)); // true
b[0].push(42);
c[0].push(42);
alert(JSON.stringify(b)); // "[[0,1,42],[0,1,42]]"
alert(JSON.stringify(c)); // "[[0,1,42],[0,1]]"