2015-01-19 2 views
1

Я пытаюсь обернуть мою голову вокруг некоторого кода в Javascript нинзя на странице 57.Javascript Ninja: Текущий элемент в массиве в контексте функции

function forEach(list, callback) { 
    for (var n = 0; n < list.length; n++) { 
     callback.call(list[n], n); //makes the current element the function context of callback??? 
    } 
} 

var weapons = ['shuriken', 'katana', 'nunchucks']; 

forEach(weapons, 
    function(index) { 
     assert(this == weapons[index], "Got the expected value of " + weapons[index]); 
    } 
); 

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

Мне также трудно понять, как это можно сделать. Я предполагаю, что метод вызова рассматривает элемент списка как объект, а не как элемент в массиве. Но я не уверен, что это правильно.

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

+1

Это код _exact_? Чтобы сделать то, что он пытается сделать, я ожидал бы, что вызов функции в цикле for будет чем-то вроде 'callback.call (list [n], n)' - Обратите внимание на дополнительный '.call' –

+0

ah ya справа. Я пропустил это благодарение за это. – rmares2

+0

Я не понимаю ваш второй абзац («Мне тяжело ...»). Не могли бы вы прояснить это немного? – JLRishe

ответ

2

Я не понимаю, почему я хочу использовать текущий элемент в качестве контекста функции.

Это позволяет вам использовать this в функции обратного вызова для обращения к каждому соответствующему текущему элементу. Это то же самое соглашение, что и метод jQuery $.each() и некоторые другие методы jQuery (автор вашей книги был создателем jQuery).

Это позволяет сделать это:

forEach([1, 2, 3], function() { 
    console.log(this * 2);  // 'this' refers to the current element 
}); 

Выход:

2 
4 
6 

Конечно, другой прекрасно подход должен пройти в текущем элементе в качестве аргумента, а не указывать контекст функции , Это то, что делает встроенный Array.prototype.forEach (по существу). Упрощенная версия такого подхода будет выглядеть так:

function forEach(list, callback) { 
    for (var i = 0; i < list.length; i++) { 
     callback(list[i], i); 
    } 
} 

forEach([1, 2, 3], function(item) { 
    console.log(item * 2); // 'item' is the current element 
}); 

Ни один из подходов не является окончательно лучше другого. Это просто, что некоторые считают, что для этого можно использовать this.

Мне также трудно понять, как это можно сделать. Я предполагаю, что метод вызова рассматривает элемент списка как объект, а не как элемент в массиве. Но я не уверен, что это правильно.

Контекст функции, переданный в call(), может быть вообще чем угодно. Он просто определяет значение, которое принимает this, когда функция выполняет (больше всего времени).

Моя другая мысль заключалась в том, что, не назначая контекст функции текущему элементу, контекст функции будет функцией forEach.

Нет, если контекст функции был неопределенным здесь, было бы null в строгом режиме, или window в режиме совместимости (если предположить, что код работает в браузере). Здесь также не было бы особенно полезно.

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

Это вызовет проблемы только в том случае, если кто-то попытался использовать this в своем обратном вызове любым значимым способом. Причина его изменения - это то, что я объяснил выше.

+0

Что это соглашение jQuery не делает его лучше ... – Bergi

+1

@Bergi Я никогда не говорил (и не подразумевал), что он это делает. – JLRishe

+0

Конечно, я просто хотел подчеркнуть, что это один из самых бедных jQuery. – Bergi

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