Подтвердить что ты не робот

Что означает "()" в вызове функции?

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

myFunction(); //there empty parens

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

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

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

"Рассмотрите возможность использования setTimeout(monitor, 100); вместо setTimeout('monitor()', 100);. Eval is evil:)"

Хлоп! Действительно ли мы eval() -в строке здесь? Наверное, я действительно не понимаю значение и значение "вызова" функции. Каковы реальные правила о вызовах и ссылках на функции?

4b9b3361

Ответ 1

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

Скажем, речь идет о функции hello,

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

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

hello

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

hello()

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

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

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

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

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

Итак, для примера функции reality вы могли бы передать любое из следующих значений в jQuery bind.

$('#foo').bind('click', reality);
$('#foo').bind('click', reality());
$('#foo').bind('click', reality()());

Ответ 2

Пример 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

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

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

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

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

Ответ 4

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

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

function x() {
    return "blah";
}

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

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

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

x();

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

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

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

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