Выразительный JavaScript (Хавербеке) - страница 46

Оператор >== сравнивает переменные объектов, проверяя, ссылаются ли они на один объект. Но иногда полезно было бы сравнить объекты по содержимому.

Напишите функцию >deepEqual, которая принимает два значения и возвращает >true, только если это два одинаковых значения или это объекты, свойства которых имеют одинаковые значения, если их сравнивать рекурсивным вызовом >deepEqual.

Чтобы узнать, когда сравнивать величины через >===, а когда – объекты по содержимому, используйте оператор >typeof. Если он выдаёт >"object" для обеих величин, значит нужно делать глубокое сравнение. Примите во внимание одно дурацкое исключение, существующее по историческим причинам: >typeof null тоже возвращает >"object".

>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

5. Функции высшего порядка

Цу-ли и Цу-су похвалялись размерами своих новых программ. «Двести тысяч строк»,- сказал Цу-ли,- «не считая комментариев!» Цу-су ответил: «Пф-ф, моя – почти миллион строк». Мастер Юнь-Ма сказал: «Моя лучшая программа занимает пятьсот строк». Услышав это, Цу-ли и Цу-су испытали просветление.

Мастер Юнь-Ма, «Книга программирования»

Есть два способа построения программ: сделать их настолько простыми, что там очевидно не будет ошибок, или же настолько сложными, что там не будет очевидных ошибок.

Энтони Хоар, 1980, лекция на вручении премии Тьюринга

Большая программа – затратная программа, и не только из-за времени её написания. Большой размер обычно означает сложность, а сложность сбивает с толку программистов. Сбитые с толку программисты делают ошибки в программах. Большая программа означает, что багам есть где спрятаться, и их получается труднее отыскать.

Вернёмся ненадолго к двум примерам из введения. Первый самодостаточен и занимает шесть строк.

>var total = 0, count = 1;

>while (count <= 10) {

>  total += count;

>  count += 1;

>}

>console.log(total);

Второй основан на двух внешних функциях и занимает одну строку.

>console.log(sum(range(1, 10)));

В каком из них скорее встретится ошибка?

Если мы добавим размер определений >sum и >range, вторая программа тоже получится большой – больше первой. Но я всё равно утверждаю, что она скорее всего будет правильной.

Это будет потому, что выражение решения непосредственно относится к решаемой задаче. Суммирование числового промежутка – это не циклы и счётчики. Это суммы и промежутки.

Определения этого словаря (функции >sum и >range) будут включать циклы, счётчики и другие случайные детали. Но потому, что они выражают более простые концепции, чем вся программа, их проще сделать правильно.