2013-11-08 5 views
1

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

Давайте рассмотрим следующий пример кода.

var friends = ["Mike", "Stacy", "Andy", "Rick"]; 

friends.forEach(function (name, index){ 
    console.log(index + 1 + ". " + name); 
}); 

Это логически выдает;

1. Mike 
2. Stacy 
3. Andy 
4. Rick 

Фактически все последующие выдают то же самое;

friends.forEach(function (index, name){ 
    console.log(name + 1 + ". " + index); 
}); 

friends.forEach(function (foo, bar){ 
    console.log(bar + 1 + ". " + foo); 
}); 

friends.forEach(function (x, y){ 
    console.log(y + 1 + ". " + x); 
}); 

Как функция обратного вызова в forEach знает, как интерпретировать name и index? Другими словами; как обратный вызов знает, что массив имеет значения и индексы? Понятно, что имя, которое вы передаете входным переменным функции обратного вызова, не важно, но порядок, так как отображаются данные?

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

ответ

3

В браузерах, которые поддерживают Array.prototype.forEach изначально он может быть реализован по-разному, но в целом вы будете использовать Function.prototype.call для выполнения функции callback снабженных аргументами в правильном порядке (что бы это ни было), пока перебор коллекции.

MDN entry для forEach имеет следующий код для его реализации массивов в браузерах, которые не поддерживают:

if (!Array.prototype.forEach) { 
    Array.prototype.forEach = function (fn, scope) { 
     'use strict'; 
     var i, len; 
     for (i = 0, len = this.length; i < len; ++i) { 
      if (i in this) { 
       fn.call(scope, this[i], i, this); 
      } 
     } 
    }; 
} 

Другими словами; как обратный вызов знает, что массив имеет значения и индексы? Понятно, что имя, которое вы передаете входным переменным функции обратного вызова, не важно, но порядок, так как отображаются данные?

Разрабатывать, функция обратного вызова просто функция, как и любой другой, с параметрами, которые могут быть произвольно названы (a и b работает так же хорошо, как и indexvalue); до его выполнения он ничего не знает о массиве. Массив, который вы вызываете forEach, знает, что он имеет индексы и что эти индексы имеют значения, а также ожидает, что функция обратного вызова будет принимать аргументы в определенном порядке. Вещи не точно сопоставлены между массивом и функцией обратного вызова, функция forEach просто передает каждый индекс и его соответствующее значение функции обратного вызова по очереди.

2

Функция ожидает три аргумента. Неважно, что они называются. Он передаст правильные значения в функцию для вас.

forEach выполняет при условии, callback один раз для каждого элемента массива с назначенным значением. Он не вызывается для индексов, которые были удалены или которые были инициализированы до undefined.

callback вызывается с тремя аргументами :

  • значение элемента
  • индекс элемента
  • массив пересекаемой

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

1

Для облегчения понимания для этого конкретного метода, давайте посмотрим на Array.prototype.forEach код совместимости:

if (!Array.prototype.forEach) { 
    Array.prototype.forEach = function (fn, scope) { 
     'use strict'; 
     var i, len; 
     for (i = 0, len = this.length; i < len; ++i) { 
      if (i in this) { 
       fn.call(scope, this[i], i, this); 
      } 
     } 
    }; 
} 

Присмотритесь на fn.call: эта строка вызывает переданную функцию обратного вызова, передавая контекст (scope), и аргументы (this[i] - текущий элемент, i - индекс, this - весь массив).

Для получения дополнительной информации о том, как вызывать функции, отличные от someFunction(arguments) посмотреть на этой ссылке:

1. Function.prototype.bind

2. Function.prototype.call

3. Function.prototype.apply

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