поведение области действия анонимной функции javascript - PullRequest
2 голосов
/ 06 февраля 2011

У меня есть код, который следует этому шаблону:

a = "abcdefghijklmnopqrstuvwxyz";
m = {};

for(i=0;i<10;i++){
  m[a.charAt(i)] = function(){
      return i;
  };
}

console.log(m.c());

он возвращает 10.

ПОЧЕМУ, черт возьми, он это делает?И как мне заставить его вернуть соответствующий номер?

------- РЕДАКТИРОВАТЬ -------

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

a = "abcdefghijklmnopqrstuvwxyz";
m = {};

f = function(i) {
    return function(){
        return i;
    }
}

for(i=0;i<10;i++){
    var eval('n') = "hi";
    console.log(n);
    m[a.charAt(i)] = function(fn){
        fn(f(i));
    };
}

m.c(function(a){console.log(a);});

, и результат согласился с моей интуицией, что это не сработает.У кого-нибудь есть идеи для этого?

Спасибо за вашу помощь

В результате вашей помощи здесь я смог запустить этот проект: https://github.com/sbussard/python-for-node

Пожалуйста, продолжайте вносить свой вклад, как вы пожелаете.

Ответы [ 3 ]

4 голосов
/ 06 февраля 2011

Переменные в цикле без их изменения.

Нежелательное поведение

> myFunctions = new Array() 
[object Array]

for(var i = 0; i < 3; ++i) myFunctions[i] = function() { return i; } 

> myFunctions[0]() 
3

> myFunctions[1]() 
3

> myFunctions[2]() 
3

Fixed

>myFunctions = new Array() 
[object Array]

function mkFunctionWithCagedValue(value) { 
    return function() { 
        return value;
    };
} 

> for(var i = 0; i < 3; ++i) myFunctions[i] = mkFunctionWithCagedValue(i) 
[object Function]

> myFunctions[0]() 
0

> myFunctions[1]() 
1

> myFunctions[2]() 
2
3 голосов
/ 06 февраля 2011

Функция ссылается на переменную i. Когда функция выполняется (в строке console.log()), она печатает переменную, которая в это время имеет значение 10.

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

for(i=0;i<10;i++){
  function use_copy() {
    var icopy = i; # a new variable to hold the value of i
    return (function(){
      # original function, now using icopy
      return icopy;
    });
  }
  m[a.charAt(i)] = use_copy();
}
0 голосов
/ 06 февраля 2011

** ИЗД. **

Ваша переменная i внутри вашего цикла равна 10 во время вызова m.c(), и поскольку она используется в вашей функции, она возвращает 10 для каждого «индекса». Просто сохраните копию этой переменной. Например:

someFunction = function() {
   alert(i);  // will alert 10 because using i from the loop!
};
a = "abcdefghijklmnopqrstuvwxyz";
m = {};

for(i=0;i<10;i++){
  m[a.charAt(i)] = (function(i, callback) {
     // i is a local copy!
     return function() {
        callback();   // invoke callback function
        return i;
     };
  })(i, someFunction);
}

console.log(m.c());  // would return 2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...