Что означает "()" в вызове функции? - PullRequest
19 голосов
/ 04 сентября 2010

Теперь я обычно вызываю функцию (которая не требует аргументов) с () следующим образом:

myFunction(); //there's empty parens

За исключением вызовов jQuery, где я могу обойтись:

$('#foo').bind('click', myFunction); //no parens

Fine.Но недавно я увидел этот комментарий здесь на SO:

«Попробуйте использовать setTimeout(monitor, 100); вместо setTimeout('monitor()', 100);. Eval is evil :)»

Yikes!Мы действительно eval() -с строкой здесь?Думаю, я не совсем понимаю значение и значение «вызова» функции.Каковы реальные правила вызова и обращения к функциям?

Ответы [ 4 ]

44 голосов
/ 04 сентября 2010

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

Допустим, речь идет о функции hello,

function hello() {
    alert('yo');
}

Когда мы просто пишем

hello

мы имеем в виду функцию, которая не выполняет ее содержимое. Но когда мы добавляем символы () после имени функции,

hello()

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

Метод bind в jQuery принимает тип события (строка) и функцию в качестве аргументов. В вашем примере вы передаете тип - «click» и фактическую функцию в качестве аргумента.

Вы видели Начало? Рассмотрим этот надуманный пример, который может прояснить ситуацию. Поскольку функции являются первоклассными объектами в JavaScript, мы можем передавать и возвращать функцию изнутри функции. Итак, давайте создадим функцию, которая возвращает функцию при вызове, а возвращенная функция также возвращает другую функцию при вызове.

function reality() {
    return function() {
        return function() {
            alert('in a Limbo');
        }
    };
}

Здесь reality - функция, reality() - функция, а reality()() - также функция. Однако reality()()() - это не функция, а просто undefined, поскольку мы не возвращаем функцию (мы ничего не возвращаем) из самой внутренней функции.

Так что для примера функции reality вы могли бы передать в привязку jQuery любое из следующего:

$('#foo').bind('click', reality);
$('#foo').bind('click', reality());
$('#foo').bind('click', reality()());
7 голосов
/ 04 сентября 2010

Ваш пример jQuery bind похож на setTimeout(monitor, 100);, вы передаете ссылку на объект функции в качестве аргумента.

Передача строки в методы setTimeout / setInterval должна бытьизбегать по тем же причинам, вы должны избегать eval и конструктора Function, когда это не нужно.

Код, переданный в виде строки, будет оцениваться и выполняться в глобальном контексте выполнения, который может дать вам: "Проблемы с областью действия ", рассмотрим следующий пример:

// a global function
var f = function () {
  alert('global');
};

(function () {
  // a local function
  var f = function() {
    alert('local');
  };

  setTimeout('f()', 100); // will alert "global"
  setTimeout(f, 100);     // will alert "local"
})();

Первый вызов setTimeout в приведенном выше примере выполнит глобальную функцию f, так как вычисляемый код не имеет доступа к локальной лексической областианонимной функции.

Если вы передадите ссылку на объект функции методу setTimeout, как во втором вызове setTimeout, будет выполнена та же самая функция, на которую вы ссылаетесь в текущей области.

3 голосов
/ 04 сентября 2010

Вы не делаете то же самое в своем примере jQuery, как во втором примере setTimeout - в своем коде вы передаете функцию и связываете событие click.

В первом примере setTimout передается функция monitor, которую можно вызывать напрямую, во втором передается строка monitor(), которая должна быть eval ed.

При передаче функции вы используете имя функции. При его вызове вы должны использовать ().

Eval вызовет то, что передано, поэтому для успешного вызова функции требуется ().

2 голосов
/ 04 сентября 2010

Прежде всего, "()" не является частью имени функции. Это синтаксис, используемый для вызова функций.

Сначала вы связываете функцию с именем идентификатора, используя объявление функции:

function x() {
    return "blah";
}

... или используя выражение функции:

var x = function() {
    return "blah";
};

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

x();

Функция setTimeout принимает и функцию, и идентификатор, или строку в качестве первого аргумента ...

setTimeout(x, 1000);
setTimeout("x()", 1000);

Если вы предоставите идентификатор, то он будет вызываться как функция. Если вы предоставите строку, то она будет оценена (выполнена).

Первый метод (с указанием идентификатора) предпочтителен ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...