Область видимости переменных javascript: возврат переменных из вложенных функций?

Я посмотрел на это: Возврат значений из вложенных функций в Javascript

но мне это не очень помогло (или я просто слишком туп, чтобы понять это).

Моя переменная область как-то отключена, и я не понимаю, почему. Мой alert() ведет себя не так, как ожидалось. Пытался добавить комментарии ко всем строкам, чтобы объяснить, о чем я думаю.

Большое спасибо за любые комментарии/указания/ответы!

var g = {}; / is a large object with all kinds of other stuff and functions in it

g.ding = function(){ // my problem function
 var baby = 'young'; // i thought I set a local var here
    if(someVar==true) { // standard issue if statement
        someAPI.class( // using an API that uses a function as its attribute
            function(stuff){ // my anonymous function
                baby = 'old'; // setting the var to something
            }
        );
    }
    return baby; // returning the var
}

alert( g.ding() ); // i expect it to say "old" but it keeps saying "young". why?

НОВАЯ РЕДАКЦИЯ: Принятый ответ Хуана великолепен, но нет ли способа использовать setTimeout() для работы с асинхронными вызовами функций и, по сути, сделать их синхронными? если любой, кто читает это, знает ответ, я хотел бы знать. Спасибо.


person tim    schedule 22.06.2012    source источник
comment
Скорее всего, потому что function(stuff) никогда не запускается. Ваш обзор выглядит нормально. Ничто здесь не доказывает, что строка кода, устанавливающая baby="old", когда-либо выполнялась. someVar может быть ложным, или someAPI никогда не сможет вызвать функцию, которую вы ему передадите.   -  person Jamie Treworgy    schedule 22.06.2012
comment
ну, изначально я проверил с помощью alert(), что эта функция вызывается. Я думаю, что асинхронный элемент функции API — это решение.   -  person tim    schedule 22.06.2012


Ответы (2)


Вызов someAPI.class(function(){}), вероятно, асинхронный, это означает, что функция, которую вы ей передаете, возможно, не была вызвана, когда someAPI.class() возвращается, и переменная не была изменена.

Решение состоит в том, чтобы передать переменную обратно в обратном вызове

g.ding = function(callback){ 
    var baby = 'young';
    if(someVar) {
        someAPI.class(
            // There's no guarantee of when this function is called
            function(stuff){
                baby = 'old';
                // Call the callback, it's like a return, for async functions
                callback(baby);
            }
        );
    }
    // the inner function probably wasn't called yet, 
    // doesn't make sense to return this here
    // return baby;
}

// Then you'd call it like this, as soon as you use an async function
// all the functions that call it have to use callbacks for return values
g.ding(function(value){
    alert(value);
});
person Juan Mendes    schedule 22.06.2012
comment
Большое спасибо, Хуан, это определенно прояснило для меня. Всегда боритесь с асинхронностью. - person tim; 22.06.2012
comment
@tim Кстати, class - это зарезервированное ключевое слово, и его не следует использовать в качестве имени свойства (если только вы не всегда используете его с someAPI["class"](), я надеюсь, что это не настоящее имя метода, который вы вызываете) - person Juan Mendes; 22.06.2012
comment
Хуан, спасибо, да, я знаю это о «классе» - я упрощал пример кода для ясности. - person tim; 25.06.2012

Здесь я могу думать, что ваш

 someAPI.class();

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

person me_digvijay    schedule 22.06.2012