Есть ли веская причина передать строку в setTimeout?

Мы все знаем, что передача строки в setTimeout (или setInterval) является злой, потому что она запущена в глобальной области, имеет проблемы с производительностью, потенциально небезопасна, если вы вводите какие-либо параметры и т.д. это явно не рекомендуется:

setTimeout('doSomething(someVar)', 10000);

в пользу этого:

setTimeout(function() {
    doSomething(someVar);
}, 10000);

Мой вопрос: может ли быть когда-нибудь причина для первого? Всегда ли это предпочтительнее? Если это не так, почему это разрешено?

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

Ответ 1

Вы всегда можете использовать глобальные переменные, обращаясь к ним как к свойствам оконного объекта, например window.globalVar (хотя использование глобальных переменных действительно не является хорошей практикой), поэтому нет, я не думаю, что когда-либо есть веская причина для используйте устаревший синтаксис.

Вероятно, это разрешено по историческим причинам: как отметил Феликс Клинг, исходный синтаксис позволил только передать строку кода:

Представлен с помощью JavaScript 1.0, Netscape 2.0. Передача ссылки объекта объекта Function была введена с помощью JavaScript 1.2, Netscape 4.0; поддерживаемый MSHTML DOM с версии 5.0. [источник, мой акцент]

Если браузеры больше не поддерживают использование строки в качестве первого аргумента для setTimeout и setInterval, в Интернете будет много кода, который больше не работает.

Ответ 2

Для тех, кто перенаправлен здесь вопросом о том, почему передача функции лучше, чем передача строки.

1: передача строки вызывает компилятор

Каждый раз, когда вам нужно оценить строку, вы запускаете полный компилятор. Для каждого вызова, где это необходимо.

Это не только медленно, но и уничтожает все ускоренные JIT и браузеры.

2: передача строки более ограничена.

Поскольку строка выполняется через компилятор, она не так сильно связана с локальной областью и переменными.

Пока это не заметно в ситуации вроде:

window.setInterval("doThing()");

В более сложной ситуации код просто чист:

window.setInterval("doThing(" + val1 + "," + val2 + ")");

против

window.setInterval(function() {
  // You can put a debugging point here
  dothing(val1, val2);
});

3: объекты DOM нельзя передать через строку

Как отметил Альваро, объекты DOM не могут передаваться строковым методом.

// There is no way to do this via a string.
var el = document.getElementById("my-element");
window.setInterval(function() {
  dothing(el);
});

(Другие объекты могут быть или не быть проходимыми - в зависимости от того, могут ли они быть сериализованы, но в целом это было бы довольно сложно.)