Я слышал, что глобальные переменные являются плохими, какое альтернативное решение следует использовать?

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

Я думаю о функции, которая при подаче двух аргументов (function globalVariables(Variable,Value)) выглядит, если Variable существует в локальном массиве, и если она устанавливает значение Value, else, Variable и Value прилагаются. Если функция вызывается без аргументов (function globalVariables()), она возвращает массив. Возможно, если функция запускается только одним аргументом (function globalVariables(Variable)), она возвращает значение Variable в массиве.

Как вы думаете? Я хотел бы услышать ваши альтернативные решения и аргументы для использования глобальных переменных.

Как использовать globalVariables();

function append(){
    globalVariables("variable1","value1"); //globalVariables() would append variable1 to it local array.
};

function retrieve(){
    var localVariable1 = globalVariables("variable1"); //globalVariables() would return "value1".
};

function retrieveAll(){
    var localVariable1 = globalVariables(); //globalVariables() would return the globalVariable() entire, local [persistently stored between calls] array.
};

function set(){
    globalVariables("variable1","value2"); //globalVariables() would set variable1 to "value2".
};

Является ли это Singleton Pattern BTW?

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

Спасибо, я ценю всю вашу помощь!

Ответ 1

Основная причина, по которой глобальные переменные обескуражены в javascript, заключается в том, что в javascript весь код использует одно глобальное пространство имен, а javascript подразумевает глобальные переменные, т.е. переменные, которые явно не объявлены в локальной области, автоматически добавляются в глобальное пространство имен. Опираясь слишком много на глобальные переменные, вы можете столкнуться с разными сценариями на одной странице (прочитайте статьи douglas crockford).

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

var FOO = (function() {
    var my_var = 10; //shared variable available only inside your module

    function bar() { // this function not available outside your module
        alert(my_var); // this function can access my_var
    }

    return {
        a_func: function() {
            alert(my_var); // this function can access my_var
        },
        b_func: function() {
            alert(my_var); // this function can also access my_var
        }
    };

})();

теперь, чтобы использовать функции в вашем модуле в другом месте, используйте FOO.a_func(). Чтобы разрешить глобальные конфликты пространства имен, вам нужно только изменить имя FOO.

Ответ 2

Семантика моего мальчика. Семантика.

Начните с одного глобального: myApp = {}; Все должно быть в этом. Единственным исключением будет ваша библиотека AJAX (есть некоторые крайние исключения, такие как работа с обратными вызовами JSONP).

В myApp должно быть очень мало свойств. Вы хотите сохранить свои свойства приложения в контейнерах, таких как config или settings.

myApp = {
    config:{
        prop:1
    },
    settings:{
        prop:2
    },
    widgets:{
        List: function(props){},
        Item: function(props){}
    }
}

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

Эта настройка дает вам дополнительное преимущество в доступе к любому свойству из любого другого места, поскольку вы можете получить его с помощью myApp global. Тем не менее, вы должны использовать "this", когда это возможно, потому что поиск выполняется быстрее. И просто установите свойство напрямую, не беспокойтесь о материалах псевдо-геттера/сеттера. Если вам действительно нужен getter/setter, введите код для этого конкретного использования.

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

И не увлекайтесь частными переменными. Они тоже плохие: http://clubajax.org/javascript-private-variables-are-evil/

Ответ 3

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

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

Также, когда вы получаете доступ или изменяете глобальную область действия, вы рискуете повлиять на другие объекты. Вот почему библиотеки, такие как jquery, используют только одно имя в глобальной области (наименее возможно). Это уменьшает вероятность конфликта с другими библиотеками. Другими словами, глобальный охват находится вне вашего контроля, поэтому он опасен.

Ответ 4

Вы действительно не хотите этого делать. Что касается того, почему, см., Например, топ-пост здесь: Каков самый код EVIL, который вы когда-либо видели в производственной корпоративной среде?

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

(function () {
    var notaglobal = 1;
    alert(notaglobal);
})();
//notaglobal is not defined in this scope        

Ответ 5

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

Рассмотрим этот фрагмент кода, который я нашел:

if (typeof session != 'undefined' && !data.cart.request_status)
  data.input_definitions.passengers =
    inflate_passenger(session, data.input_definitions.passengers);

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

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

Обходной путь с использованием ES6:

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

import {Sesssion} from 'api-core';
const Session = require('api-core').session;

Если вы используете код доставки для браузера, вы не можете использовать import, если вы не перекроете свой код ES6, используя Babel.

Пример трансляции с использованием Gulp.js:

// $ npm install --save-dev gulp-babel babel-preset-es2015

// gulpfile.js
const gulp  = require('gulp');
const babel = require('gulp-babel');

gulp.task('transpile', () => {
  return gulp.src('src/app.js')
    .pipe(babel({presets: ['es2015']}))
    .pipe(gulp.dest('dist'));
});

// $ gulp transpile

Обходной путь устаревшего:

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

// scripts/app.js
var MyApp = {
  globals: {
    foo: "bar",
    fizz: "buzz"
  }
};

Ответ 6

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

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

Ответ 7

Другой ответ больше всего объясняет анонимной функцией как этот упоминается в статье,

Анонимные функции трудно отлаживать, поддерживать, тестировать или повторно использовать.

Вот пример с нормальной функцией. Это легче читать и понимать.

/* global variable example */

    var a= 3, b= 6;
    
    function fwithglobal(){
    console.log(a, b); // 3 6 expected
    }
    
    fwithglobal(); // first call
    
    function swithglobal(){
    var a=9;
    console.log(a, b); // not 3 6 but 9 6
    }
    
    swithglobal(); // second call
    

/* global variable alternative(function parameter) */

    function altern(){
    var a= 3, b= 6; // var keyword needed
      f_func(a,b);
      s_func(a,b);
    }
    
    function f_func(n, m){
    console.log(n, m); // 3 6 expected
    }
    
    function s_func(n, m){
    var a=9;
    console.log(n, m); // 3 6 expected
    }
    
    altern(); // only once

Ответ 8

Глобальные переменные плохо... если оставить неуправляемым!

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

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

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