2013-06-22 5 views
0

Я пытаюсь создать 2 синусоидальных волны и добавить их вместе, чтобы создать третью. Я могу добавить их тонкой и вывода результата на консоль, но всякий раз, когда я пытаюсь поставить это значение в массив, я получаю ошибку:Невозможно получить доступ к переменной Javascript: undefined

«Не удается прочитать свойство„1“неопределенных»

Может ли кто-нибудь объяснить, где я ошибаюсь? Jsfiddle здесь: http://jsfiddle.net/YJqZz/

d1 = []; 
d2 = []; 
d3 = []; 

// Sample the sine function 
for (i = 0; i < 2 * Math.PI; i += 0.02) { 
    d1.push([i, 15+Math.sin(5*i)]); 
    d2.push([i, 10+Math.sin(4*i)]); 
    console.log(d1[i][1] + d2[i][1]); 
    d = d1[i][1] + d2[i][1]; 
    console.log(d); 
    d3.push([i,d]); 
} 
+0

Похоже, 'd1 [I]' или 'd2 [I]' не существует. Если 'd1 [i]' не определено, вы не можете выполнить 'undefined [1]' –

+2

, когда вы нажимаете(), ваши элементы будут иметь целые индексы, такие как '2'. но ваша переменная i не является int, ее чем-то вроде «0.04» – goat

ответ

4

Чтобы получить доступ к последнему элементу в dX использования dx[dX.length - 1].

Ваш i находится здесь (0.02). Значение, не являющееся целым числом, передается в строку. Затем объект Array интерпретируется как обычный объект (вид карты). В объекте нет ключа "0.02", поэтому dX["0.02"] оценивает undefined. Вы не можете получить доступ к undefined, следовательно, к ошибке.

+1

* «Значение, а не целое число, вызывается в строку». * Индексы массива - это * всегда * строки. (В классических JavaScript-массивах, а не в новых.) (Не поймите меня неправильно, я думаю, что я был вашим первым upvote, потому что это был первый ответ, чтобы правильно проверить его. Я просто говорю. .) –

+0

Индексы массивов никогда не являются строками. Синтаксис индексатора [значение] обращается к индексам массива или свойствам объекта. Если вы используете число, подобное [0], номер используется как-есть - не передается в строку - и получает доступ к значению массива при индексе 0, если таковой имеется. Если вы используете строку типа ['Name'], она получает доступ к свойству объекта с именем «Name», если таковое имеется. Это идентично доступу к a.Name. –

4

Вы пытаетесь получить доступ к элементам в массиве с удвоениями, так как ваш цикл увеличивается на 0.02. Клавиши массива задаются как целые числа при нажатии, поэтому этот метод не будет работать.

Я переработан код, чтобы использовать объекты вместо: http://jsfiddle.net/YJqZz/2/

d1 = {}; 
d2 = {}; 
d3 = {}; 

// Sample the sine function 
for (i = 0; i < 2 * Math.PI; i += 0.02) { 
    d1[i] = [i, 15+Math.sin(5*i)]; 
    d2[i] = [i, 10+Math.sin(4*i)]; 
    console.log(d1[i][1] + d2[i][1]); 
    d = d1[i][1] + d2[i][1]; 
    console.log(d); 
    d3[i] = [i,d]; 
} 
+0

@ T.J.Crowder Да, действительно, вы правы. Я немного изменю. – Jivings

+0

@ Вы прокомментировали это, прежде чем я отредактировал. – Jivings

+0

Всегда ставьте соответствующий код в самом ответе, а не просто на ссылку. (Даже с jsFiddle.) Почему: http://meta.stackexchange.com/questions/118392/add-stack-overfow-faq-entry-or-similar-for-putting-code-in-the-question Я был в там все равно фиксирует опечатку, поэтому я просто скопировал ее для вас. –

1

Есть много проблем с этим кодом.

Во-первых, добавление поплавков в таком цикле увеличит двоичные ошибки в формате с плавающей запятой, пока они не станут очевидными в выходе. Попробуйте запустить этот код:

var a = []; 
for (var i = 0; i < 2 * Math.PI; i += 0.02) 
    a.push(i); 

$('#output').html(a.join('<br/>')); 

http://jsfiddle.net/b9chris/AwT5c/

Посмотрите на значения он генерируется. Вероятно, это не то, что вы ожидали. Эти безумные числа являются результатом того, как сохраняются числа с плавающей запятой - десятичная часть хранится как двоичные десятичные числа, поэтому 1/2 + 1/4 + 1/8 + .... 0.02 не может быть точно представлен в этом формате, поэтому система приближается к нему, а затем округляет значение до десяти десятичных знаков, когда оно возвращается, покрывая затуманенное базовое значение. Но дополнения выполняются в двоичном формате, и в итоге аппроксимации складываются и раскрывают эту проблему.

Решение вместо этого цикла с целыми числами и разделить как можно позже:

http://jsfiddle.net/b9chris/AwT5c/1/

Во-вторых, ваше состояние цикл включает в себя операцию, которая всегда возвращает один и тот же результат. Это отнимает процессорное время - цикл for будет постоянно пересчитывать значение 2 * Math.PI только для получения одного и того же результата в каждом цикле. Вы можете решить эту проблему, сохранив ее в переменной и запустив вместо нее цикл.

Возможно, вы не понимаете, как работает Array.push(). Вы передаете ему значение для push, и оно автоматически присваивает это следующему индексу в массиве.Так что это, работать на массиве с 1 значением в нем:

a.push([5, 10]); 

добавляет значение с индексом 1 (не 5), и это значение является сам массив 2-элемента, [5, 10]. Итак, где вы делали это:

d1.push([i, 1]); 
var d = d1[i][1]; 

Вы складывали значение по индексу 0, например, а затем пытается получить его обратно в индекс 0,02. Поскольку ваша цель - напрямую обращаться к ним по индексу, нецелесообразно использовать push, тогда предположим, что индекс соответствует тому, что находится в счетчике цикла (например, что, если в массиве уже добавлены значения). Вместо этого назначьте указатель напрямую, что допустимо в Javascript.

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

var d1 = []; 
var d2 = []; 
var d3 = []; 

var inverseStep = 50; // 1/.02 
var l = 2 * Math.PI * inverseStep; 

for (var i = 0; i < l; i++) { 
    var ix = i/inverseStep; 

    d1[i] = [ix, 15+Math.sin(5*ix)]; 
    d2[i] = [ix, 10+Math.sin(4*ix)]; 
    var d = d1[i][1] + d2[i][1]; 
    d3[i] = [ix, d]; 
} 

$('#output').html(d3.join('<br/>')); 

http://jsfiddle.net/b9chris/AwT5c/3/