Время от времени я встречаю публикации, где рассказывается о том, какие из значений оператора ==
эквивалентны (как, например, здесь). Часто при этом оговаривается, что приведённые в таблице данные не очень хорошо организованы.
Я согласен, такие таблицы нужны, чтобы лучше ориентироваться в несовершенствах оператора… вот только несовершенства в организации данных в самих таких таблицах, на мой взгляд ещё больше усложняют ситуацию. Вот, к примеру, таблица из ссылки, приведённой выше:
Кошмар, товарищи!.. Как по мне, так здесь бóльший беспорядок в очерёдности строк/столбцов.
Сгруппировав их по наличию пересечений мы получим более внятную картину:
Так легче ориентироваться, не правда ли? А ещё такая организация таблицы позволяет сразу увидеть несовершенства ==
.
Код
Ниже приведён код, который я использовал для создания моей версии этой таблицы. Он доступен на jsfiddle.
HTML
<canvas id="drawCanvas" width="500" height="500" />
JavaScript
var cmp = function(v1, v2) { return v1 == v2; };
var vals = [
["false", function() { return false; }],
["0", function() { return 0; }],
['""', function() { return ""; }],
["[[]]", function() { return [[]]; }],
["[]", function() { return []; }],
['"0"', function() { return "0"; }],
["[0]", function() { return [0]; }],
["[1]", function() { return [1]; }],
['"1"', function() { return "1"; }],
["1",function() { return 1; }],
["true", function() { return true; }],
["-1", function() { return -1; }],
['"-1"', function() { return "-1"; }],
["null", function() { return null; }],
["undefined", function() { return undefined; }],
["Infinity", function() { return Infinity; }],
["-Infinity", function() { return -Infinity; }],
['"false"', function() { return "false"; }],
['"true"', function() { return "true"; }],
["{}", function() { return {}; }],
["NaN", function() { return NaN; }]
];
var canvas = document.getElementById("drawCanvas");
var ctx = canvas.getContext("2d");
var n = vals.length;
var r = 20; // diameter of grid squares
var p = 60; // padding space for labels
// color grid cells
for (var i = 0; i < n; i++) {
var v1 = vals[i][1]();
for (var j = 0; j < n; j++) {
var v2 = vals[j][1]();
var eq = cmp(v1, v2);
ctx.fillStyle = eq ? "orange" : "white";
ctx.fillRect(p+i*r,p+j*r,r,r);
}
}
// draw labels
ctx.fillStyle = "black";
var f = 12;
ctx.font = f + "px Helvetica";
for (var i = 0; i < n; i++) {
var s = vals[i][0];
var w = ctx.measureText(s).width;
ctx.save();
ctx.translate(p+i*r+r/2-f*0.4,p-w-2);
ctx.rotate(3.14159/2);
ctx.fillText(s, 0, 0);
ctx.restore();
}
for (var i = 0; i < n; i++) {
var s = vals[i][0];
var w = ctx.measureText(s).width;
ctx.fillText(s, p-w-2, p+i*r+r/2+f*0.4);
}
// draw grid lines
ctx.beginPath();
ctx.strokeStyle = "black";
for (var i = 0; i <= n; i++) {
ctx.moveTo(p+r*i, p);
ctx.lineTo(p+r*i, p+r*n);
ctx.moveTo(p, p+r*i);
ctx.lineTo(p+r*n, p+r*i);
}
ctx.stroke();
Резюме
Оператор ==
в JavaScript совершенно интранзитивен и ущербен. И хоть его недостатки с лихвой покрываются использованием ===
, он не настолько ужасен, как показано в некоторых таблицах…
Апдейт
Это было труднее, но всё же получилось сделать таблицу истинности для оператора <
(смотрим на jsfiddle):
Таблица истинности для оператора сравнения по форме напоминает треугольник, если расположить её значения в правильном порядке.
(Кстати, принцип упорядочивания значений в таблице истинности для сравнения, не всегда подходит для составления таблиц равенства.)
P.S. от переводчика
Хочется обратить ваше внимание на обсуждение данной статьи на Reddit. На самом деле у оригинальной организации таблицы есть вполне себе веские основания:
Автор: uoziod