2014-10-27 6 views
4
var inner = function() { console.log(x); } 

// test 1 
(function(cb) { var x = 123; cb(); })(inner); 

// test 2 
(function(cb) { var x = 123; cb.apply(this); })(inner); 

// test 3 
(function(cb) { var x = 123; cb.bind(this)(); })(inner); 

// test 4 
(function(cb) { cb.bind({x: 123})(); })(inner); 

Все тесты привести: ReferenceError: х не определенДоступ к локальной переменной внутри функции обратного вызова

ли кто-нибудь знает, как можно получить доступ к «х» в качестве локальной переменной внутри функции обратного вызова?

+1

Какая проблема вы пытаетесь решить? переменные в функции являются локальными для этой функции. – Hrishi

+2

Какой странный комментарий, почему это имеет значение, в чем проблема? ОП задал вопрос низкого уровня JS, который имеет прямой ответ. – Adam

+0

JavaScript имеет * лексический * объем, а не динамическую область. –

ответ

6

Факт: когда вы делаете var inner = function() { console.log(x); } в вашей первой строке, x не определен. Зачем? Потому что внутри вашей функции inner нет локального объявления x (что было бы сделано с var x = something). Затем среда выполнения будет выглядеть в следующей области, то есть в глобальной области. Существует также не объявление x, поэтому x также не определено там.

Единственные места, где есть переменная, называемая x, находятся внутри каждого из следующих 4 IIFE. Но внутри IIFE каждый x - это другая переменная, в разной степени. Итак, если вы хотите, чтобы console.log()x, определенный внутри каждого IIFE, вы принимаете неправильный подход.

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

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

Чтобы решить эту проблему, вы должны передать значение, которое вы хотите console.log() внутри функции inner в качестве параметра функции inner, а так:

var inner = function(x) { console.log(x); } 
// test 1 
(function(cb) { var x = 123; cb(x); })(inner); 
+0

Что делать, если я не могу изменить функцию обратного вызова для передачи в переменной, потому что она является частью структуры? Есть ли способ сделать это? Благодарю. –

+0

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

2

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

var inner = function(some_var) { console.log(some_var); }; //logs 123 
(function(cb) { var x = 123; cb(x); })(inner); 

ИЛИ

var inner = function(some_var) { console.log(some_var); }; //logs 123 
(function(cb) { var x = 123; cb.apply(this,[x]); })(inner); 

ИЛИ

var inner = function(some_var) { console.log(some_var); }; //logs 123 
(function(cb) { var x = 123; cb.call(this,x); })(inner); 

ДАЛЬШЕ

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

0

Вы можете переопределить функцию обратного вызова в текущая область:

var inner = function() { console.log(x); } 

(function(cb) { var x = 123; eval('cb = ' + cb.toString()); cb(); })(inner); 

// or 

(function(cb) { var x = 123; eval('(' + cb.toString() + ')')(); })(inner); 

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

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