Dostęp do zmiennych z innych funkcji bez użycia zmiennych globalnych

Słyszałem z różnych miejsc, że zmienne globalne są z natury paskudne i złe, ale kiedy robię jakiś Nie obiektowy Javascript, nie widzę, jak ich uniknąć. Powiedzmy, że mam funkcję, która generuje liczbę za pomocą złożonego algorytmu przy użyciu liczb losowych i takich tam, ale muszę nadal używać tej konkretnej liczby w jakiejś innej funkcji, która jest wywołaniem zwrotnym lub czymś takim, a więc nie może być częścią tej samej funkcji.

Jeśli pierwotnie wygenerowana liczba jest zmienna lokalna, nie będzie stamtąd dostępna. Gdyby funkcje były metodami obiektowymi, mógłbym uczynić numer właściwością, ale nie są one i wydaje się nieco skomplikowane, aby zmienić całą strukturę programu, aby to zrobić. Czy zmienna globalna jest naprawdę taka zła?

Author: Andreas Grech, 2009-01-02

10 answers

Aby zmienna obliczona w funkcji a była widoczna w funkcji B, masz trzy opcje:

  • make it a global,
  • niech będzie właściwością obiektu, lub
  • podaj go jako parametr podczas wywoływania B z A.

Jeśli twój program jest dość mały, to globale nie są takie złe. W przeciwnym razie rozważyłbym użycie trzeciej metody:

function A()
{
    var rand_num = calculate_random_number();
    B(rand_num);
}

function B(r)
{
    use_rand_num(r);
}
 56
Author: Paul Stephenson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-02 15:22:21

Myślę, że najlepszym rozwiązaniem tutaj może być zdefiniowanie pojedynczej zmiennej o globalnym zasięgu i wrzucenie tam zmiennych:

var MyApp = {}; // Globally scoped object

function foo(){
    MyApp.color = 'green';
}

function bar(){
    alert(MyApp.color); // Alerts 'green'
} 

Nikt nie powinien krzyczeć na Ciebie za zrobienie czegoś takiego jak wyżej.

 82
Author: Triptych,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-07 02:57:15

Rozważ użycie przestrzeni nazw:

(function() {
    var local_var = 'foo';
    global_var = 'bar'; // this.global_var and window.global_var also work

    function local_function() {}
    global_function = function() {};
})();

Zarówno local_function jak i global_function mają dostęp do wszystkich zmiennych lokalnych i globalnych.

Edit : inny wspólny wzór:

var ns = (function() {
    // local stuff
    function foo() {}
    function bar() {}
    function baz() {} // this one stays invisible

    // stuff visible in namespace object
    return {
        foo : foo,
        bar : bar
    };
})();

Właściwości return ed mogą być teraz dostępne poprzez obiekt przestrzeni nazw, np. ns.foo, zachowując jednocześnie dostęp do lokalnych definicji.

 15
Author: Christoph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-02 16:00:04

To, czego szukasz, jest technicznie znane jako currying.

function getMyCallback(randomValue)
{
    return function(otherParam)
    {
        return randomValue * otherParam //or whatever it is you are doing.
    }

}

var myCallback = getMyCallBack(getRand())

alert(myCallBack(1));
alert(myCallBack(2));

Powyższa funkcja nie jest dokładnie funkcją curry, ale osiąga wynik utrzymania istniejącej wartości bez dodawania zmiennych do globalnej przestrzeni nazw lub wymagania od niej innego repozytorium obiektów.

 8
Author: AnthonyWJones,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-02 15:30:05

Uznałem to za bardzo pomocne w stosunku do pierwotnego pytania:

Zwróć wartość, którą chcesz użyć w functionOne, następnie wywołaj functionOne w functionTwo, a następnie umieść wynik w nowym var i odwołaj się do nowego var w functionTwo. Powinno to umożliwić użycie var zadeklarowanego w functionOne, wewnątrz functionTwo.

function functionOne() {
  var variableThree = 3;
  return variableThree;
}

function functionTwo() {
  var variableOne = 1;
  var var3 = functionOne();

  var result = var3 - variableOne;

  console.log(variableOne);
  console.log(var3);
  console.log('functional result: ' + result);
}

functionTwo();
 5
Author: gav_aus_web,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-12 08:04:18

Jeśli inna funkcja musi użyć zmiennej, przekazujesz ją do funkcji jako argument.

Również zmienne globalne nie są z natury paskudne i złe. Tak długo, jak są używane prawidłowo, nie ma z nimi problemu.

 4
Author: Adam Peck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-02 15:21:27

Jeśli jest szansa, że użyjesz tego kodu ponownie, prawdopodobnie dołożyłbym starań, aby przejść z perspektywy obiektowej. Używanie globalnej przestrzeni nazw może być niebezpieczne - istnieje ryzyko, że trudno będzie znaleźć błędy z powodu nazw zmiennych, które zostaną ponownie użyte. Zazwyczaj zaczynam od korzystania z podejścia obiektowego do niczego więcej niż proste wywołanie zwrotne, tak, że nie muszę robić rzeczy re-write. Za każdym razem, gdy masz grupę powiązanych funkcji w javascript, myślę, że jest to kandydat do podejścia obiektowego.

 2
Author: tvanfosson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-02 15:22:24

Inne podejście to takie, które wybrałem z posta na forum Douglasa Crockforda ( http://bytes.com/topic/javascript/answers/512361-array-objects )...

Douglas Crockford napisał (a):

Jul 15 '06

"Jeśli chcesz odzyskać obiekty według id, powinieneś użyć obiektu, a nie / align = "left" / Ponieważ funkcje są również obiektami, można przechowywać członków w funkcjonować samodzielnie."

function objFacility(id, name, adr, city, state, zip) {

    return objFacility[id] = {

        id: id,
        name: name,
        adr: adr,
        city: city,
        state: state,
        zip: zip

    }
}

objFacility('wlevine', 'Levine', '23 Skid Row', 'Springfield', 'Il', 10010);

"obiekt można uzyskać za pomocą"

objFacility.wlevine

Obiekty właściwości są teraz dostępne z poziomu dowolnej innej funkcji.

 2
Author: Joel Erenberg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-12 23:13:37

Nie znam szczegółów Twojego problemu, ale jeśli funkcja potrzebuje wartości, może to być parametr przekazywany przez wywołanie.

Globale są uważane za złe, ponieważ globale stan i wiele modyfikatorów może tworzyć trudne do naśladowania kod i dziwne błędy. Wielu aktorów bawiących się czymś może wywołać chaos.

 1
Author: Arthur Thomas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-02 15:23:26

Możesz całkowicie kontrolować wykonywanie funkcji javascript (i przekazywać zmienne między nimi) za pomocą niestandardowych zdarzeń jQuery....Powiedziano mi, że nie było to możliwe na wszystkich tych forach, ale mam coś, co działa dokładnie tak (nawet za pomocą połączenia ajax).

Oto odpowiedź (ważne: nie jest to sprawdzona odpowiedź, ale raczej odpowiedź przeze mnie"Emile"):

Jak uzyskać zmienną zwracaną przez wiele funkcji-Javascript / jQuery

 1
Author: Kyle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:29