2015-03-19 3 views
1

Может ли кто-нибудь прояснить этот момент для меня?Функции закрывания и обратного вызова JavaScript

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

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

doNested(); 
function doNested() { 
    var message='Hello'; 
    window.setTimeout(inner, 3000); 
    function inner() { 
     alert(message); 
    } 
} 

Невозможно передать параметр внешней функции обратного вызова. Например:

doSeparated(); 
function doSeparated() { 
    var message='Goodbye'; 
    window.setTimeout(outer,3000); 
} 
function outer() { 
    alert(message); 
} 

Это не работает, конечно.

Вопрос в том, есть ли способ передать внутренние переменные внешней функции, подобной этой, вместо добавления их в список параметров?

Благодаря

+0

Обычно данные передаются в функции как аргументы. – zerkms

ответ

1

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

Это правильно. Каждая функция в JavaScript имеет доступ только к тем переменным, которые либо определены в его собственной области видимости, либо определены в родительской области . Поэтому ваш первый пример работает, пока ваш второй пример не работает.

Вопрос в том, есть ли способ передать внутренние переменные внешней функции, подобной этой, вместо добавления их в список параметров?

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

doSeparated(); 
 

 
function doSeparated() { 
 
    var message = "Goodbye"; 
 

 
    setTimeout(outer.bind({ 
 
     message: message 
 
    }), 3000); 
 
} 
 

 
function outer() { 
 
    alert(this.message); 
 
}

Поскольку вы используете setTimeout, вы можете передать дополнительные аргументы setTimeout, которые будут даны в функции обратного вызова. Это позволяет избавиться от неприятных bind:

doSeparated(); 
 

 
function doSeparated() { 
 
    var message = "Goodbye"; 
 
    setTimeout(outer, 3000, message); 
 
} 
 

 
function outer(message) { 
 
    alert(message); 
 
}

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

doSeparated(); 
 

 
function doSeparated() { 
 
    var message = "Goodbye"; 
 
    setTimeout(outer(message), 3000); 
 
} 
 

 
function outer(message) { 
 
    return function() { 
 
     alert(message); 
 
    }; 
 
}

Кроме них, нет никакого другого хорошего решения, которое Я могу думать. Лучшее решение - ваше оригинальное вложенное решение.


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

Смежные вопросы