Подтвердить что ты не робот

Ограничение побочных эффектов при программировании javascript в браузере

Ограничивающие побочные эффекты при программировании в браузере с помощью javascript довольно сложны.

Я могу делать такие вещи, как не обращаться к переменным-членам, как в этом глупом примере:

let number = 0;

const inc = (n) => {
  number = number + n;

  return number;
};

console.log(inc(1));  //=> 1
console.log(inc(1));  //=> 2

Но что еще я могу сделать, чтобы уменьшить побочные эффекты в моем javascript?

4b9b3361

Ответ 1

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

  • Используйте веб-работников. См. MDN. Веб-рабочие запускаются в другом глобальном контексте, который отличается от текущего.:

  • Изолировать определенные типы логики внутри iframe. Используйте кросс-окна сообщений для связи с iframe.

  • Библиотеки неизменности. См. https://github.com/facebook/immutable-js. Также http://bahmutov.calepin.co/avoid-side-effects-with-immutable-data-structures.html.

  • Заблокируйте свои объекты Object.freeze, Object.seal, или Object.preventExtensions. В том же духе создайте свойства только для чтения на объектах с помощью Object.defineProperty с геттерами, но не с настройками, либо с параметром writeable, установленным на false.

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

  • Если доступно, используйте Proxy для полного контроля доступа к объекту.

По соображениям предотвращения доступа к window см. javascript sandbox - модуль для предотвращения ссылки на Window. Также http://dean.edwards.name/weblog/2006/11/sandbox/. Наконец, Полубоксация Javascript eval.

Полезно различать внутренние побочные эффекты и внешние побочные эффекты. Внутренние побочные эффекты - это то, где какой-то другой код вторгается в состояние моего компонента. Внешние побочные эффекты - это то, где мой код вторгается в состояние какого-либо другого компонента. Внутренние побочные эффекты могут быть предотвращены с помощью IIFE, упомянутых в других ответах, или с помощью модулей ES6. Но более серьезной проблемой являются внешние побочные эффекты, которые потребуют одного из подходов, упомянутых выше.

Ответ 2

Просто то, что подсказывает мне, думая о вашем вопросе:

  • Не загрязнять глобальное пространство имен. Используйте "var" или "let", эти ключевые слова ограничивают ваши переменные локальной областью.

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

  • Используйте точки с запятой
    Раздел комментариев этой статьи дает некоторые хорошие (реальные) причины всегда использовать точки с запятой.

  • Не объявлять String, Number или Boolean Objects
    (в случае, если вам когда-либо захотелось)

    var m = new Number(2);
    var n = 2;
    m === n; // will be false because n is a Number and m is an object
    
  • "use strict"; - ваш друг. Включение строгого режима - хорошая идея, но, пожалуйста, не добавляйте его в существующий код, так как он может сломать что-то, и вы не можете действительно объявлять строгую только в лексических областях или отдельных сценариях как указано здесь

  • Сначала объявить переменные. Одним из распространенных побочных эффектов является то, что люди не знают о подъеме JavaScript. Подъем ищет ваш блок для объявления переменных и перемещает их все вместе в верхнюю часть вашего блока.

    function(){
        var x = 3;
        // visible variables at runtime at this point: x,y,i !
    
        // some code....
    
        var y = 1; // y will be moved to top!
        for( var i = 0; i < 10; i++ ){ // i will be moved to top!
            // some code...
        }
    }
    

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

  • используйте '===' вместо '=='. Есть много веских причин для этого, и это один из самых распространенных "побочных эффектов" или "ошибок" в JavaScript. Для получения дополнительной информации см. Этот отличный ответ на SO, но позвольте мне дать вам краткую демонстрацию:

    '' == '0'           // false
    0 == ''             // true
    
    // can be avoided by using '==='
    '' === '0'          // false
    0 === ''            // false
    
  • Использовать IIFE. IIFE (Expression Expression Function Expression) позволяет объявить анонимную функцию, которая будет вызывать себя. Таким образом, вы можете создать новую лексическую область и не должны беспокоиться о глобальном пространстве имен.

  • Будьте осторожны с прототипами. Имейте в виду, что объекты JavaScript того же класса имеют один и тот же прототип. Изменение прототипа означает изменение поведения экземпляров all класса. (Даже те, которые используются другими скриптами/фреймворками), как это случилось здесь

    Object.prototype.foo = function(){...} // careful!
    

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

Ответ 3

Мой любимый трюк - просто использовать язык, который компилируется в javascript, вместо использования javascript.

Однако вы можете сделать два важных трюка:

  • запустите файл "use strict";. Это включит проверку вашего кода и предотвратит использование необъявленных переменных. Да, это специальная строка, с которой браузер будет знать, как с этим бороться.
  • При необходимости используйте функции. Javascript не может выполнять обычные области, но для функций он отлично работает, поэтому получите (function() { })(); в вашей мышечной памяти.

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