Итерационные функции jQuery

Функции итератора jQuery, подобные каждой, имеют синтаксис, подобный следующему:

.each(function(index, element))

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

function my_func(index, element){
  alert(index+":"+element);
}

Для меня это дает 2 возможных объявления:

$("li").each(my_func);

или же

$("li").each(function(index, element) {alert(index+":"+element);});

Первый смущает меня, потому что я не вижу index или же element перешел к my_func, Есть ли какая-то магия в jQuery, которая знает, что my_func принимает 2 параметра, которые each обеспечивает?

Во-вторых, если бы я объявил

var my_func= function(index, element){
  alert(index+":"+element);
}

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

И наконец, большинство each реализации, которые я вижу, делают что-то вроде этого:

$("li").each(function(){alert(this)});

Все параметры являются необязательными для each Перезвоните?

1 ответ

Решение

Способы передачи функции в качестве обратного вызова

В этом:

$("li").each(my_func);

Вы просто передаете ссылку на my_func к .each() метод. Каждый метод сам передает два аргумента этой функции при вызове. Если вы хотите получить доступ к этим двум аргументам, вы можете объявить их как аргументы в своем собственном определении my_func, но вы не должны. Аргументы будут там, независимо от того, объявите ли вы их или нет.

Вы можете объявить my_func несколькими различными способами:

// somewhat normal way and you can easily access the index and element arguments
function my_func(index, element) {
     // code here
}

// if you don't need index and element, you don't need to declare them
// but they are still actually there and can be reached via the arguments object
function my_func() {
     // code here
     console.log(arguments[0]);   // index
}

Объявление функций сvar

Разница между:

var my_func= function(index, element){
  alert(index+":"+element);
}

а также

function my_func(index, element){
  alert(index+":"+element);
}

во многом один из сроков. Во-вторых, my_func определяется как функция, как только файл javascript, в котором он находится, обнаруживается и анализируется, а область, в которой он определен, становится действующей и становится доступной "как если бы" он был объявлен в самой верхней части области, в которой он определен, Это часто называют "подъемом", когда определение поднимается до верхней части области, в которой оно определено.

Во-первых, my_func не является функцией ДО того, что строка JS выполняется в обычном потоке выполнения этого файла javascript.

Помимо времени, вы можете в значительной степени использовать два взаимозаменяемо. Если лично предпочитаешь function xxx() формы, потому что тогда мне не нужно беспокоиться о том, вызывается ли функция до запуска объявления, но это действительно личный стиль.


Нужно ли объявлять аргументы обратного вызова

На ваш последний вопрос, вам нужно только объявить аргументы для вашего обратного вызова, если вы хотите их использовать. В javascript функция является точно такой же функцией, независимо от того, объявляете ли вы ее с аргументами или нет (не в таких языках, как C++), поэтому вам нужно только объявить их, если вы хотите получить к ним доступ по имени.

Объявления аргументов функции в javascript являются необязательными. Вы можете объявить больше, чем передано в функцию, и вы можете объявить меньше, чем передано в функцию. Ни один из них не вызывает каких-либо ошибок в JavaScript.

Допустим, у вас есть этот код:

 function callWithDelay(t, fn, arg1, arg2) {
     setTimeout(function() {
         fn(arg1, arg2);
     }, t);
 }

Ожидаемый способ использовать это - определить функцию, которая принимает два аргумента и передать ее как fn аргумент.

 function myFunc(msg, color) {
     var obj = document.getElementById("error")
     obj.innerHTML = msg;
     obj.style.color = color;
 }

 callWithDelay(2000, myFunc, "Both first and last name are required", "red");

Но вам не нужно передавать функцию, которая имеет именно эти аргументы. Вы можете сделать это следующим образом (доступ к аргументам через arguments объект, а не по имени):

 function myFunc() {
     var obj = document.getElementById("error")
     obj.innerHTML = arguments[0];
     obj.style.color = arguments[1];
 }

 callWithDelay(2000, myFunc, "Both first and last name are required", "red");

Или вы можете передать функцию, которая даже не нуждается в этих аргументах:

 function myFunc() {
     document.getElementById("error").style.display = "none";
 }

 callWithDelay(2000, myFunc);

callWithDelay Функция не заботится о том, какую ссылку на функцию вы передаете. Это может быть буквально любая функция. callWithDelay Функция передаст два аргумента обратному вызову, который был передан ей при вызове, но только принимающая функция должна решать, использует ли она эти аргументы. В последнем примере я оставил два последних аргумента callWithDelay когда это называлось. Когда вы пропускаете аргумент (в конце списка вызовов), этот аргумент просто undefined, В JavaScript undefined является законной ценностью. Итак, когда я оставляю их вне вызова callWithDelay(2000, myFunc), они есть undefined и поэтому undefined это то, что передается myFunc обратный вызов как два аргумента. В этом случае, поскольку эти аргументы не используются, никого не волнует, что они undefined,


Перегрузка функций - проверка того, какие типы аргументов были переданы

В javascript вы также можете проверить, какой тип аргументов был передан функции, и соответствующим образом адаптировать свое поведение. Например, допустим, у вас есть простая функция, которая скрывает элемент DOM:

function hide(elem) {
    elem.style.display = "none";
}

// usage
var obj = document.getElementById("test");
hide(obj);

Эта функция предполагает, что elem является элементом DOM и будет работать, только если это то, что передано. Но что, если мы также хотим позволить кому-то передать id элемента. Мы могли бы изучить аргумент, который передается hide и посмотреть, если это строка, и, если так, мы можем рассматривать ее как значение идентификатора.

function hide(elem) {
    // if a string was passed, find the DOM object using that string as an id
    if (typeof elem === "string") {
        elem = document.getElementById(elem);
    }
    elem.style.display = "none";
}

// first usage
var obj = document.getElementById("test1");
hide(obj);

// second uage
hide("test2");

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

function hide(elem) {
    // if a string was passed, find the DOM object using that string as an id
    if (typeof elem === "string") {
        document.getElementById(elem).style.display = "none";
    } else if (typeof elem === "object" && Object.prototype.toString.call(elem) === "[object Array]") {
        // an array was passed
        for (var i = 0; i < elem.length; i++) {
            elem[i].style.display = "none";
        }
    } else {
        // only a single DOM element was passed
        elem.style.display = "none";
    }
}

// usages
hide(obj);
hide([obj1, obj2, obj3]);
hide("test");
Другие вопросы по тегам