2013-03-26 3 views
2

Итак, сегодня я начал обходиться с JavaScript, и я наткнулся на забавный случай, когда он кажется убежденным в том, что что-то является функцией, а также убежден, что это не функция. Этот код иллюстрирует проблему:JavaScript: TypeError с массивом функций

var arr1 = Array(1) 
for (i = 0; i < arr1.length; i++) { 
    arr1[i] = function(n) { return n + i } 
} 

var arr2 = Array(1) 
for (j = 0; j < arr2.length; j++) { 
    arr2[j] = function(n) { return arr1[j](n) } 
} 

typeof arr2[0] // "function" 
arr2[0](2)  // TypeError: Property '1' of object [object Array] is not a function 

Здесь вы можете назначить переменную arr2[0], и ошибка не будет устранена. Я не уверен, нужны ли закрытия или массивы, чтобы воспроизвести это.

Есть что-то с моим кодом, или это только одна из тех странностей JavaScript? Это не то, что я особенно нуждаюсь в ответе, но это немного глупо, поэтому я хотел бы знать, есть ли причина для этого.

+1

Почему 'Массив (1)' и контур вместо 'вар arr1 = [функция (п) {возвращения N + 1;}];'? –

+0

Возможный дубликат [Закрытие Javascript внутри петель - простой практический пример] (http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – bfavaretto

+0

Это изначально произошло, когда я экспериментировал с массивы замыканий по индексам цикла, поэтому я просто сохранил это так: – boxes

ответ

2

Это фактически делает есть немного сделать с закрытием.

Во-первых, принять этот код:

for (j = 0; j < arr2.length; j++) { 
    arr2[j] = function(n) { return arr1[j](n) } 
} 

Переменная j изначально содержит значение 0, таким образом, arr2[0] устанавливается в качестве ссылки на функцию.

Далее, j увеличивается и теперь имеет значение 1. Это завершает цикл.

Теперь когда функция вызывается:

return arr1[j](n) 

Из-за закрытия, j до сих пор имеет конечное значение, равное 1. Что является недействительным индекс в этом массиве.

Еще одна вещь, чтобы указать. Цикл for не создает нового закрытия, поэтому, если вы ожидаете анонимной функции , заключите значение j внутри этой итерации, это предположение неверно. Будет один экземпляр j в пределах всей функции, которая была объявлена ​​j.

+0

А, это имеет смысл (и я узнал, что индекс вне пределов возвращает 'undefined', а не бросает ошибку). Спасибо за быстрый ответ. – boxes

+0

Да, массивы просто становятся мешками для имущества, как и любой другой объект. Нет ничего, что помешало бы вам установить 'arr2 [50]' или 'arr2 ['bananas']' если хотите. –

0

Это не делает ничего странного.

Вы просто пытаетесь что-то, что не является функцией (значение arr1[1], которое равно undefined).

0

Это, вероятно, безопаснее для инициализации массивов в виде:

var arr1 = []; 

Или, если вы используете «Массив» вы должны инициализировать его следующим образом:

var arr1 = new Array(); 
1

Я думаю, вы пытаетесь использовать замыкание внутри цикла, но это не работает.

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

var arr1 = Array(1) 
for (i = 0; i < arr1.length; i++) { 
    arr1[i] = (function(i){ 
     return function(n) { 
      return n + i 
     }; 
    })(i); 
} 

var arr2 = Array(1) 
for (j = 0; j < arr2.length; j++) { 
    arr2[j] = (function(j){ 
     return function(n) { 
      return arr1[j](n) 
     } 
    })(j); 
} 

typeof arr2[0] 
arr2[0](2) 

Демонстрация: Fiddle

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