Почему неизменяемость так важна (или необходима) в JavaScript?

в настоящее время я работаю над реагировать JS и Реагировать Уроженца основы. На полпути я наткнулся на неизменность или неизменяемый-JS библиотека, когда я читал о реализации Flux и Redux Facebook.

вопрос в том, почему неизменность так важна? Что плохого в мутации объектов? Разве это не упрощает дело?

приводя пример, рассмотрим простой Новости app с открывающимся экраном, являющимся списком заголовков новостей.

Если я говорю массив объектов со значением изначально я не могу управлять ею. Так говорит принцип неизменности, верно? (Поправьте меня, если я ошибаюсь.) Но что, если у меня есть новый новостной объект, который должен быть обновлен? В обычном случае я мог бы просто добавить объект в массив. Как мне достичь в этом случае? Удалить хранилище и воссоздать его? Не добавляет объект в массив a менее дорогая операция?

PS: Если пример не является правильным способом объяснить неизменность, пожалуйста, дайте мне знать, что является правильным практическим примером.

10 ответов


Я недавно исследовал ту же тему. Я сделаю все возможное, чтобы ответить на ваш вопрос(ы) и попытаться поделиться тем, что я до сих пор узнал.

вопрос в том, почему неизменность так важна? Что не так в мутирующие объекты? Разве это не упрощает дело?

В основном это сводится к тому, что неизменность повышает предсказуемость, производительность (косвенно) и допускает мутацию отследить.

прогнозируемость

мутация скрывает изменения, которые создают (неожиданные) побочные эффекты, которые могут вызвать неприятные ошибки. Когда вы применяете неизменность, вы можете сохранить архитектуру приложения и ментальную модель простыми, что облегчает рассуждение о вашем приложении.

производительность

даже если добавление значений к неизменяемому объекту означает, что новый экземпляр должен быть создан там, где существует значения должны быть скопированы и новые значения должны быть добавлены к новому объекту, который стоит памяти, неизменяемые объекты могут использовать структурный общий доступ для уменьшения накладных расходов памяти.

все обновления возвращают новые значения, но внутренние структуры являются общими для резко сократить использование памяти (и GC thrashing). Это означает, что если вы добавляете к вектору 1000 элементов, он фактически не создает новый вектор 1001-элементов. Скорее всего, внутренне лишь несколько маленький выделяются объекты.

вы можете узнать больше об этом здесь.

Отслеживая Мутации

кроме уменьшенного использования памяти, immutability позволяет вам оптимизировать ваше применение путем использовать равность ссылки и значения. Это делает его действительно легко увидеть, если что-то изменилось. Например, изменение состояния в компоненте react. Вы можете использовать shouldComponentUpdate чтобы проверить, идентично ли состояние, сравнивая объекты состояния и предотвращение ненужного рендеринга. Вы можете прочитать больше об этом здесь.

дополнительные материалы:

Если я установил, скажем, массив объектов со значением изначально. Я не могу манипулировать ею. Вот что говорит принцип неизменности, правильно?(Правильный я, если я ошибаюсь). Но, что, если у меня есть новый новостной объект, который должен быть в курсе? В обычном случае я мог бы просто добавить объект в матрица. Как мне достичь в этом случае? Удалить магазин и воссоздать его? Не является ли добавление объекта в массив менее дорогостоящей операцией?

Да, это правильно. Если вы смущены тем, как реализовать это в своем приложении, я бы рекомендовал вам посмотреть, как redux делает это, чтобы ознакомиться с основные концепции, они мне очень помогли.

мне нравится использовать Redux в качестве примера, потому что он охватывает неизменность. Он имеет единственное неизменяемое дерево состояний (называемое store), где все изменения состояния явны путем отправки действий, которые обрабатываются редуктором, который принимает предыдущее состояние вместе с указанными действиями (по одному) и возвращает следующее состояние вашего приложения. Вы можете прочитать больше о его основных принципах здесь.

там отличный курс redux на яйцеголовый.Ио где Дэн Абрамов, автор redux, объясняет эти принципы следующим образом (я немного изменил код, чтобы лучше соответствовать сценарию):

import React from 'react';
import ReactDOM from 'react-dom';

// Reducer.
const news = (state=[], action) => {
  switch(action.type) {
    case 'ADD_NEWS_ITEM': {
      return [ ...state, action.newsItem ];
    }
    default: {
        return state;
    }
  }
};

// Store.
const createStore = (reducer) => {
  let state;
  let listeners = [];

  const subscribe = (listener) => {
    listeners.push(listener);

    return () => {
      listeners = listeners.filter(cb => cb !== listener);
    };
  };

  const getState = () => state;

  const dispatch = (action) => {
    state = reducer(state, action);
    listeners.forEach( cb => cb() );
  };

  dispatch({});

  return { subscribe, getState, dispatch };
};

// Initialize store with reducer.
const store = createStore(news);

// Component.
const News = React.createClass({
  onAddNewsItem() {
    const { newsTitle } = this.refs;

    store.dispatch({
      type: 'ADD_NEWS_ITEM',
      newsItem: { title: newsTitle.value }
    });
  },

  render() {
    const { news } = this.props;

    return (
      <div>
        <input ref="newsTitle" />
        <button onClick={ this.onAddNewsItem }>add</button>
        <ul>
          { news.map( ({ title }) => <li>{ title }</li>) }
        </ul>
      </div>
    );
  }
});

// Handler that will execute when the store dispatches.
const render = () => {
  ReactDOM.render(
    <News news={ store.getState() } />,
    document.getElementById('news')
  );
};

// Entry point.
store.subscribe(render);
render();

кроме того, эти видео демонстрируют более подробно, как достичь неизменности для:


Противоположный Взгляд на неизменность

короткий ответ: неизменность-это скорее тенденция моды, чем необходимость в JavaScript. Есть несколько узких случаев, когда это становится полезным (в основном React/Redux), хотя обычно по неправильным причинам.

длинный ответ: читайте ниже.

почему неизменяемость так важна(или необходима) в javascript?

Ну, я рад, что вы спросили!

некоторое время назад очень талантливый парень позвонил Дэн Абрамов написал библиотеку управления состоянием javascript под названием Redux, который использует чистые функции и неизменности. Он также сделал некоторые действительно здорово видео это сделало идею очень простой для понимания (и продажи).

время было идеальным. Новизна Угловое угасал, и мир JavaScript был готов зациклиться на последней вещи, которая имела правильную степень крутости, и эта библиотека была не только инновационной, но и прорезано идеально с реагировать который продавался другим электростанция Силиконовой долины.

как это ни печально, мода правит в мире JavaScript. Теперь Абрамова называют полубогом, и все мы, простые смертные, должны подчиниться Дао неизменяемости... Имеет это смысл или нет.

что плохого в мутации объектов?

ничего!

на самом деле программисты мутировали объекты для er... пока есть объекты для мутации. 50+ лет разработки приложений другими словами.

а зачем все усложнять? Когда у вас есть объект cat и он умирает, вам действительно нужна секунда cat отслеживать изменения? Большинство людей просто сказали бы cat.isDead = true и покончим с этим.

Не (мутирующие объекты) делают вещи просто?

да! .. Ну конечно!

специально в JavaScript, который на практике наиболее полезен для рендеринга представления некоторого состояния, которое поддерживается в другом месте (например, в базе данных).

что делать, если у меня есть новый объект новостей, который должен быть обновлен? ... Как мне достичь в этом случае? Удалить магазин и воссоздать его? Не является ли добавление объекта в массив менее дорогостоящей операцией?

Ну, вы можете пойти традиционный подход и обновление News object, поэтому ваше представление в памяти этого объекта изменяется (и представление, отображаемое пользователю, или так можно было бы надеяться)...

или наоборот...

вы можете попробовать сексуальный подход FP / Immutability и добавить свои изменения в News объект к массиву, отслеживающему каждое историческое изменение таким образом, вы можете выполнить итерацию по массиву и выяснить, каким должно быть правильное представление состояния (фу!).

Я пытаюсь узнать, что здесь. Пожалуйста, просветите меня :)

мода приходит и уходит, дружище. Есть много способов освежевать кошку.

мне жаль, что вам приходится нести путаницу постоянно меняющегося набора парадигм программирования. Но эй, добро пожаловать в клуб!!

теперь несколько важных моментов, чтобы помнить о неизменности, и вы получите эти брошены на вас с лихорадочным интенсивность, которую может вызвать только наивность.

1) неизменяемость является удивительным для избежания состояний гонки в многопоточных средах.

многопоточные среды (например, C++, Java и C#) виновны в практике блокировки объектов, когда несколько потоков хотят их изменить. Это плохо для производительности, но лучше, чем альтернатива повреждения данных. И все же не так хорошо, как сделать все неизменным (Хвала Господу Хаскелл!).

НО УВЫ! В JavaScript, вы всегда работать на одном потоке. Даже веб-работники (каждый работает внутри отдельный контекст). Так как вы не можете иметь нить отношение состояние гонки внутри вашего контекста выполнения (Все эти прекрасные глобальные переменные и замыкания), основной момент в пользу неизменности выходит из окна.

(сказав, что там is преимущество к использованию чистого функции в web workers, то есть вы не будете иметь никаких ожиданий о возиться с объектами в основном потоке.)

2) неизменность может (как-то) избежать условий гонки в состоянии вашего приложения.

и вот реальная суть вопроса, большинство (React) разработчиков скажут вам, что неизменность и FP могут каким-то образом работать эту магию, которая позволяет состоянию вашего приложения стать предсказуемым.

конечно, это не означает, что вы может избежать условия гонки в базе данных, чтобы вытащить это, вам придется координировать все пользователи во всех браузерах, и для этого вам понадобится технология back-end push, такая как WebSockets (подробнее об этом ниже), который будет транслировать изменения на все запущенные приложения.

это довольно запутанное утверждение просто означает, что последние значения, назначенные объекту состояния (определяемому одним пользователем, работающим в своем браузере), становятся предсказуемый. Что на самом деле совсем не прогресс. Потому что вы могли бы использовать обычную старую измененную переменную для отслеживания вашего состояния, и вы знаете, что имеете дело с последней информацией, когда вы обращаетесь к ней, и это будет работать с чем угодно, кроме React/Redux.

почему? Потому что React особенный.. и состояние компонента управляется через цепочку событий, которые вы не контролируете и полагаетесь на вас помня не мутировать состояние непосредственно. Это было обработано удивительно с точки зрения PR, поскольку шумиха React превратила недостаток в сексуальную моду. Мода в сторону, я бы предпочел видеть неизменность для того, что это такое, т. е. инструмент для затыкания пробела, когда ваш выбор фреймворка не обрабатывает состояние интуитивно.

3) условия гонки категорически плохо.

Ну, они могут быть, если вы используете React. Но они редки, если вы выбираете другую структуру.

кроме того, у вас обычно есть далеко большие проблемы для решения ... проблем, таких как зависимость ад. Как раздутая кодовая база. Например, ваш CSS не загружается. Как медленный процесс сборки или застрять в монолитном фоновом режиме, что делает итерацию почти невозможной. Как неопытные разработчики, не понимающие, что происходит, и создающие беспорядок.

вы знаете. Реальность. Но кого это волнует?

4) неизменяемость использует Ссылка Типа уменьшить влияние на производительность отслеживания каждого изменения состояния.

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

5) неизменяемость позволяет отменить вещи.

потому, РП.. это функция номер один, о которой попросит ваш руководитель проекта, верно?

6) неизменяемое состояние имеет большой потенциал в сочетании с WebSockets

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

как только Пенни падает на эту концепцию (состояниепоток событий -- вместо грубого набора записей, представляющих последний взгляд), неизменный мир становится волшебным местом для обитания. Земля событие-добыт интересно и возможно, что превосходит само время. И когда все сделано правильно, это определенно может сделать приложения в реальном времени easiЭр для этого вы просто транслируете поток событий всем заинтересованным, чтобы они могли построить свое собственное представление настоящего и записать свои собственные изменения в общий поток.

но в какой-то момент Вы просыпаетесь и понимаете, что все это чудо и магия не приходят бесплатно. В отличие от ваши энергичные коллеги, ваши заинтересованные стороны (да, люди, которые вам платят) мало заботятся о моде и много о деньгах, которые они платят за создание продукта, который они могут продать. И суть в том, что труднее написать неизменяемый код и легче его сломать, плюс мало смысла иметь неизменяемый передний конец, если у вас нет заднего конца для его поддержки. Когда (и если!) Вы, наконец, убедить ваших заинтересованных сторон, что вы должны публиковать и потреблять события через push techology как WebSockets, вы узнаете, что боль это масштабирование в производстве.


теперь несколько советов, Если вы решите принять его.

выбор для написания JavaScript с использованием FP / Immutability также является выбором, чтобы сделать вашу базу кода приложения больше, сложнее и сложнее управлять. Я бы настоятельно рекомендовал ограничить этот подход вашими редукторами Redux.. если вы не знаете, что вы делаете. Другими словами: просто Сохранить Ее Простой.™ в большинстве случаев вам будет лучше. А там, где вас нет, я бы сосредоточился на получении преимущества неизменяемых данных, проходящих через ваше (целое) приложение, а не создавать чисто функциональный интерфейс и называть дело сделано.

If you paid someone to draw you a horse, which one would you rather?

теперь, если вам посчастливилось сделать выбор в своей работе, попробуйте использовать свою мудрость (или нет) и делайте то, что правильно для человека, который платит вы. Вы можете основывать это на своем опыте, на своей интуиции или на том, что происходит вокруг вас (по общему признанию, если все используют React/Redux, тогда есть веский аргумент, что будет легче найти ресурс для продолжения вашей работы).. Кроме того, вы можете попробовать либо Возобновить Разработку или Hype Driven Development подходы. Они могут быть больше в твоем вкусе.

вкратце, вещь, котор нужно сказать для immutability что оно будет сделать вас модным со своими сверстниками, по крайней мере, до следующего увлечения, к этому моменту вы будете рады двигаться дальше.


теперь я добавил Это как статью в своем блоге =>неизменяемость в JavaScript: противоположное представление. Не стесняйтесь отвечать там, если у вас есть сильные чувства, которые вы тоже хотели бы снять с груди ;).


вопрос в том, почему неизменность так важна? Что плохого в мутации объектов? Разве это не упрощает дело?

на самом деле, все наоборот: изменчивость делает вещи более сложными, по крайней мере в долгосрочной перспективе. Да, это делает ваше начальное кодирование проще, потому что вы можете просто изменить вещи, где хотите, но когда ваша программа становится больше, это становится проблемой – если значение изменилось, что изменилось?

когда вы делаете все неизменный, это означает, что данные больше не могут быть изменены неожиданностью. Вы точно знаете, что если вы передаете значение в функцию, оно не может быть изменено в этой функции.

проще говоря: если вы используете неизменяемые значения, это очень легко рассуждать о вашем коде: каждый получает уникальную* копию ваших данных, поэтому он не может futz с ним и сломать другие части вашего кода. Представьте, насколько это упрощает работу в многопоточной среде!

Примечание 1: существует потенциал производительность неизменность в зависимости от того, что вы делаете, но такие вещи, как неизменное.js оптимизируют как можно лучше.

примечание 2: в маловероятном случае вы не были уверены, неизменный.js и ES6 const означать очень разные вещи.

в обычном случае я мог бы просто добавить объект в массив. Как мне достичь в этом случае? Удалить магазин и воссоздать его? Не является ли добавление объекта в массив менее дорогостоящей операцией? PS: Если пример не является правильный способ объяснить неизменность, пожалуйста, дайте мне знать, какой правильный практический пример.

Да, ваш пример новостей совершенно хорош, и ваши рассуждения совершенно правы: вы не можете просто изменить свой существующий список, поэтому вам нужно создать новый:

var originalItems = Immutable.List.of(1, 2, 3);
var newItems = originalItems.push(4, 5, 6);

хотя другие ответы прекрасны, чтобы ответить на ваш вопрос о практическом случае использования (из комментариев к другим ответам), давайте выйдем за пределы вашего рабочего кода на минуту и посмотрим на вездесущий ответ прямо у вас под носом: git. Что произойдет, если каждый раз, когда вы нажимаете фиксацию, вы overwrote данные в репозитории?

теперь мы находимся в одной из проблем, с которыми сталкиваются неизменяемые коллекции: раздувание памяти. Git достаточно умен чтобы не просто создавать новые копии файлов каждый раз, когда вы вносите изменения,он просто отслеживает изменения.

хотя я мало знаю о внутренней работе git, я могу только предположить,что он использует аналогичную стратегию библиотек, на которые вы ссылаетесь: структурный обмен. Под капотом библиотеки используют нах или другие деревья, чтобы отслеживать только узлы, которые отличаются.

эта стратегия также достаточно эффективна для данных в памяти структуры как есть известный алгоритмы работы с деревом, которые работают в логарифмическом времени.

другой вариант использования: скажем, вы хотите кнопку отмены на вашем webapp. С неизменяемыми представлениями ваших данных реализация таких относительно тривиальна. Но если вы полагаетесь на мутацию, это означает, что вам нужно беспокоиться о кэшировании состояния мира и создании атомарных обновлений.

короче говоря, есть цена, которую нужно заплатить за неизменность производительности во время выполнения и кривая обучения. Но любой опытный программист скажет вам, что время отладки на порядок превышает время написания кода. И небольшое влияние на производительность выполнения, вероятно, перевешивается связанными с состоянием ошибками, которые ваши пользователи не должны терпеть.


Почему неизменяемость так важна(или необходима) в JavaScript?

неизменяемость можно отслеживать в разных контекстах, но наиболее важным было бы отслеживать его против состояния приложения и против пользовательского интерфейса приложения.

Я буду рассматривать шаблон JavaScript Redux как очень модный и современный подход, и потому что вы упомянули об этом.

для пользовательского интерфейса нам нужно сделать это предсказуемым. Это будет предсказуемо, если UI = f(application state).

приложения (в JavaScript) изменяют состояние с помощью действий, реализованных с помощью функция редуктора.

функция редуктора просто принимает действие и старое состояние и возвращает новое состояние, сохраняя старое состояние нетронутым.

new state  = r(current state, action)

enter image description here

преимущество: вы путешествуете во времени по состояниям, так как все объекты состояния сохранены, и вы можете отобразить приложение в любом состоянии, так как UI = f(state)

таким образом, вы можете отменить/повторить легко.


случается, что создание всех этих состояний все еще может быть эффективной памятью, аналогия с Git велика, и у нас есть аналогичная аналогия в ОС Linux с символическими ссылками (на основе индексов).


вопрос в том, почему неизменность так важна? Что плохого в мутации объектов? Разве это не упрощает дело?

о переменчивости

нет ничего плохого в изменчивости с технической точки зрения. Это быстро, это повторное использование памяти. Разработчики привыкли к этому с самого начала (насколько я помню). Проблема существует в использовании изменчивости и неприятностей, которые это использование может принести.

Если объект не используется совместно с чем-либо, например, существует в области действия функции и не подвергается воздействию извне, тогда трудно увидеть преимущества в неизменности. Действительно в этом случае нет смысла быть неизменными. Чувство неизменности возникает, когда чем-то делятся.

головная боль изменчивости

изменяемая общая структура может легко создать много подводных камней. Любое изменение в любой части кода с доступом к ссылке влияет на другие части с видимостью этой ссылки. Такой удар соединяет все части совместно, даже когда они не должны быть осведомлены различных модулей. Мутация в одной функции может привести к сбою совершенно другой части приложения. Это плохой побочный эффект.

следующая часто проблема с мутацией-поврежденное состояние. Поврежденное состояние может произойти при сбое процедуры мутации в середине, и некоторые поля были изменены, а некоторые нет.

более того, с мутацией трудно отслеживать изменения. Простая проверка справки не будет покажите разницу, чтобы узнать, что изменилось, нужно сделать глубокую проверку. Также для мониторинга изменения необходимо ввести некоторую наблюдаемую закономерность.

наконец, мутация является причиной недостаточного доверия. Как вы можете быть уверены, что какая-то структура имеет желаемое значение, если она может быть мутирована.

const car = { brand: 'Ferrari' };
doSomething(car);
console.log(car); // { brand: 'Fiat' }

как показано выше, передача изменяемой структуры всегда может закончиться, имея другую структуру. Функция doSomething мутирует атрибут, заданный извне. Нет доверяйте коду, вы действительно не знаете, что у вас есть и что у вас будет. Все эти проблемы происходят потому, что: изменяемые структуры представляют указатели на память.

неизменяемость - это значения

неизменность означает,что изменение не выполняется на одном и том же объекте, структуре, но изменение представлено в новом. И это потому, что reference представляет значение не только указателя памяти. Каждое изменение создает новое значение и не касается старый. Такие четкие правила возвращают доверие и предсказуемость кода. Функции безопасны в использовании, потому что вместо мутации они имеют дело с собственными версиями с собственными значениями.

использование значений вместо контейнеров памяти дает уверенность в том, что каждый объект представляет определенное неизменяемое значение и безопасно его использовать.

неизменяемые структуры представляют значения.

я погружаюсь еще больше в тему в средней статье - https://medium.com/@macsikora/the-state-of-immutability-169d2cd11310


еще одно преимущество неизменности в Javascript заключается в том, что она уменьшает временную связь, что имеет существенные преимущества для дизайна в целом. Рассмотрим интерфейс объекта с двумя методами:

class Foo {

      baz() {
          // .... 
      }

      bar() {
          // ....
      }

}

const f = new Foo();

это может быть так, что вызов baz() требуется, чтобы получить объект в допустимом состоянии для вызова bar() для правильной работы. Но откуда ты это знаешь?

f.baz();
f.bar(); // this is ok

f.bar();
f.baz(); // this blows up

чтобы понять это, вам нужно тщательно изучить внутренние элементы класса, потому что это не сразу видно из изучения публичного интерфейса. Эта проблема может взорваться в большой кодовой базе с большим количеством изменяемых состояний и классов.

если Foo является неизменным, то это уже не проблема. Можно с уверенностью предположить, что мы можем вызвать baz или bar в любом порядке, потому что внутреннее состояние класса не может изменить.


когда-то была проблема с синхронизацией данных между потоками. Эта проблема была большой болью, было 10+ решений. Некоторые пытались решить ее радикально. Это было место, где зародилось функциональное программирование. Это как марксизм. Я не мог понять, как Дэн Абрамов продал эту идею в JS, потому что она однопоточная. Он гений.

Я могу привести маленький пример. Существует атрибут __attribute__((pure)) в gcc. Компиляторы пытаются решить, функция чиста или нет, если вы не будете declear его специально. Ваша функция может быть чистой, даже ваше состояние изменчиво. Неизменность-это всего лишь один из 100 способов гарантировать, что ваша функция будет чистой. На самом деле 95% ваших функций будет чистым.

вы не должны использовать какие-либо ограничения (например, неизменность), если у вас на самом деле нет серьезной причины. Если вы хотите "отменить" некоторое состояние, вы можете создавать транзакции. Если вы хотите упростить связь, вы можете отправлять события с помощью immutable данные. Это зависит от вас.


Другое Взять...

мой другой ответ касается вопроса с очень практической точки зрения, и мне все еще нравится. Я решил добавить это как еще один ответ, а не добавление к нему, потому что это скучная философская тирада, которая, надеюсь, также отвечает на вопрос, но на самом деле не соответствует моему существующему ответу.

TL; DR

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

гораздо, гораздо больше ответов

Примечание: для целей этого ответа я использую слово "дисциплина", чтобы означать самоотречение для некоторой пользы.

это похоже по форме на другой вопрос: "Должен ли я использовать Typescript? Почему типы так важны в JavaScript?". У него тоже есть аналогичный ответ. Рассмотрим следующий сценарий:

вы являетесь единственным автором и сопровождающим кодовой базы JavaScript/CSS/HTML некоторых 5000 строк. Ваш полутехнический босс читает что-то о том, что Typescript-as-the-new-hotness и предлагает нам перейти к нему, но оставляет решение за вами. Поэтому вы читаете о нем, играете с ним и т. д.

Итак, теперь у вас есть выбор, вы переходите к Typescript?

Typescript имеет некоторые неоспоримые преимущества: intellisense, раннее обнаружение ошибок, предварительное указание API, простота исправления при рефакторинге, меньшее количество тестов. Машинописный текст также есть некоторые затраты: некоторые очень естественные и правильные идиомы JavaScript могут быть сложными для моделирования в не особенно мощной системе типов, аннотации увеличивают LoC, время и усилия перезаписи существующей кодовой базы, дополнительный шаг в конвейере сборки и т. д. Более фундаментально, он вырезает подмножество возможных правильных программ JavaScript в обмен на обещание, что ваш код скорее чтобы быть правильным. Это произвольно ограничивает. В этом весь смысл.: вы накладываете некоторую дисциплину, которая ограничивает вас (надеюсь, от стрельбы в ногу).

вернемся к вопросу, перефразированному в контексте вышеуказанного абзаца: это стоит?

в описанном сценарии я бы утверждал, что если вы очень хорошо знакомы с кодовой базой JS от малого до среднего, то выбор использования Typescript более эстетичен, чем практичен. И это штраф в размере, нет ничего неправильно С эстетика, они просто не всегда убедительны.

Сценарий B:

вы меняете работу и теперь являетесь программистом линии бизнеса в Foo Corp. вы работаете с командой из 10 на кодовой базе 90000 LoC (и подсчета) JavaScript/HTML/CSS с довольно сложным конвейером сборки, включающим babel, webpack, набор polyfills, react с различными плагинами, систему управления состоянием, ~20 сторонних библиотек, ~10 внутренних библиотек, Плагины редактора, такие как linter с правилами для внутреннего руководства по стилю и т. д. так далее.

назад, когда вы были 5K LoC парень / девушка, это просто не имело большого значения. Даже документации не было это большое дело, даже возвращаясь к определенной части кода через 6 месяцев, вы могли бы понять это достаточно легко. Но теперь дисциплина не просто хорошая, а необходимые. Эта дисциплина может не включать в себя машинопись, но будет вероятно, включают в себя некоторую форму статического анализа, как а также все другие формы дисциплины кодирования (документация, руководство по стилю, скрипты сборки, регрессионное тестирование, CI). Дисциплина больше не роскошь, это необходимость.

все это относится к GOTO в 1978 году: ваша маленькая игра в блэкджек в C может использовать GOTOS и логика спагетти, и это было не так уж важно, чтобы выбрать свое собственное приключение, но по мере того, как программы становились все больше и амбициознее, ну, недисциплинированный использование GOTO не удалось сохранить. И все это относится и к неизменности.

как и статические типы, если вы не работаете над большой кодовой базой с командой инженеров, поддерживающих/расширяющих ее, выбор в пользу неизменности более эстетичен, чем практичен: это преимущества все еще есть, но не может перевешивать затраты еще.

но, как и во всех полезных дисциплинах, наступает момент, когда он больше не является необязательным. если я хотите поддерживать здоровый вес, тогда дисциплина с участием мороженого может быть необязательной. Но если я хочу быть конкурентоспособным спортсменом, мой выбор, есть ли мороженое или нет, зависит от моего выбора целей. Если вы хотите изменить мир с помощью программного обеспечения, неизменности может быть частью того, что вам нужно, чтобы избежать его разрушения под собственным весом.


Я думаю, что основная причина неизменяемых объектов - это сохранение состояния объекта.

Предположим у нас есть объект, называемый arr. Этот объект действителен, если все элементы имеют одинаковую букву.

// this function will change the letter in all the array
function fillWithZ(arr) {
    for (var i = 0; i < arr.length; ++i) {
        if (i === 4) // rare condition
            return arr; // some error here

        arr[i] = "Z";
    }

    return arr;
}

console.log(fillWithZ(["A","A","A"])) // ok, valid state
console.log(fillWithZ(["A","A","A","A","A","A"])) // bad, invalid state

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