Иногда я вижу JavaScript, который написан с аргументом, который уже имеет заданное значение или является объектом с методами. Возьмите пример jQuery, например:
$(".selector").children().each(function(i) {
console.log(i);
});
При регистрации i
вы получите значение того, что i
нахожу в этой итерации, когда смотрю на дочерних селекторов в each
методе jQuery.
Возьмите пример Node.js:
http.createServer(function(request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}).listen(8888);
Здесь вы можете увидеть, что request
и response
передаются, и они содержат свои собственные методы, на которые можно воздействовать.
Для меня это похоже на передачу функции функции createServer
с двумя аргументами, у которых уже есть методы.
Мой вопрос многогранный:
- Откуда берутся эти аргументы?
- Если это просто анонные функции, как они получают аргументы, которые могут действовать как другие функции?
- Как создать функции, которые могут принимать мои собственные аргументы?
- Использует ли это силу закрытия?
Ответ 1
Для меня это похоже на передачу функции функции createServer с двумя аргументами, у которых уже есть методы.
Нет. Они передавали функцию createServer
которая принимает два аргумента. Эти функции позже будут вызываться с любым аргументом, который вводит вызывающий. Например:
function caller(otherFunction) {
otherFunction(2);
}
caller(function(x) {
console.log(x);
});
Будет печатать 2.
Более продвинутый, если это не то, что вы хотите, вы можете использовать метод привязки, принадлежащий ко всем функциям, который создаст новую функцию с уже связанными аргументами. например:
caller(function(x) {
console.log(x);
}.bind(null, 3);
});
Теперь напечатаем 3, и аргумент 2, переданный анонимной функции, станет неиспользуемым и неназванным аргументом.
Во всяком случае, это плотный пример; проверьте связанную документацию для bind
чтобы понять, как привязка работает лучше.
Ответ 2
Давайте рассмотрим $.each
для примера:
each: function (obj, callback, args) {
var value,
i = 0,
length = obj.length,
isArray = isArraylike(obj);
if (args) {
if (isArray) {
for (; i < length; i++) {
value = callback.apply(obj[i], args);
if (value === false) {
break;
}
}
} else {
for (i in obj) {
value = callback.apply(obj[i], args);
if (value === false) {
break;
}
}
}
// A special, fast, case for the most common use of each
} else {
if (isArray) {
for (; i < length; i++) {
value = callback.call(obj[i], i, obj[i]);
if (value === false) {
break;
}
}
} else {
for (i in obj) {
value = callback.call(obj[i], i, obj[i]);
if (value === false) {
break;
}
}
}
}
return obj;
}
Это вызвано из
$(".selector").children().each(function(i) {
console.log(i);
});
как:
return $.each.call(this, callback /* this is your function */, args /* which is an additional thing people rarely use*/ )
Это строка (в первом блоке), на которой вы хотите посмотреть
callback.call(obj[i], i, obj[i]);
Он вызывает обратный вызов и передает объект как контекст - вот почему вы можете использовать this
в цикле. Затем итерация i
а затем тот же объект, что и контекст, отправляется как аргументы для обратного вызова. Это немного похоже на волшебство; пока вы не посмотрите на исходный код.
Ответ 3
Да, вы передаете функции в качестве аргументов. Разумеется, функции, которые вы проходите, имеют свои собственные аргументы.
И эти аргументы могут быть любыми, включая объекты, которые могут иметь свои собственные методы и т.д.
http.createServer
примет функцию, и он будет знать, как могут аргументы, которые имеют функцию. Один из способов сделать это - проверить свойство arguments
переданной функции. Или разработчик api мог использовать фактические элементы.
Писатель этой функции будет знать, что ожидается в качестве аргументов, и задокументирует его в api documentation
.
Ответ 4
Если вы посмотрите на код для createServer, он будет выглядеть примерно так:
function createServer (handleRequestAndResponseFunction) {
handleRequestAndResponseFunction(actualRequest, actualReponse);
}
хорошо, нет, это не так, но это простой пример. createServer принимает function
которая принимает два аргумента.
В более реалистичных терминах, когда вы передаете эту функцию из двух аргументов, она выполняет любую промежуточную обработку и все, что ей нужно, а затем вызывает эту функцию, передавая свои собственные переменные запроса и ответа.
Ответ 5
Здесь приведен пример передачи параметров в анонимную функцию
var a = 'hello';
// Crockford
(function(a){alert(a)}(a));
// Others
(function(a){alert(a)})(a);
Он использует закрытие, поскольку это анонимная функция (на самом деле все зависит от того, как вы ее написали)