Вызов функции без скобок
мне сказали сегодня, что можно вызвать функцию без скобок. Единственный способ, который я мог придумать, это использовать такие функции, как apply или call.
f.apply(this);
f.call(this);
но они требуют круглых скобок на apply и call оставив нас на одной площади. Я также рассматривал идею передачи функции в какой-то обработчик событий, такой как setTimeout:
setTimeout(f, 500);
но тогда возникает вопрос: "как вы вызвать setTimeout без скобок?"
так каково же решение этой загадки? Как можно вызвать функцию в Javascript без использования скобок?
6 ответов:
существует несколько различных способов вызова функции без скобок.
предположим, у вас есть эта функция определена:
function greet() { console.log('hello'); }затем здесь следуют некоторые способы вызова
greetбез скобок:1. Как Конструктор
С
newвы можете вызвать функцию без скобок:new greet; // parentheses are optional in this construct.синтаксис
new constructor[([arguments])]2. Как
toStringилиvalueOfреализация
toStringиvalueOfспециальные методы: они вызываются неявно, когда преобразование необходимо:var obj = { toString: function() { return 'hello'; } } '' + obj; // concatenation forces cast to string and call to toString.вы можете (ab)использовать этот шаблон для вызова
greetбез скобок:'' + { toString: greet };или
valueOf:+{ valueOf: greet };2.б переопределение
valueOfфункции Прототипвы можете взять предыдущую идею, чтобы переопределить
valueOfметодFunctionпрототип:Function.prototype.valueOf = function() { this.call(this); // Optional improvement: avoid `NaN` issues when used in expressions. return 0; };как только вы это сделаете, вы можете написать:
+greet;и хотя есть круглые скобки, связанные вниз по линии, фактический запуск вызова не имеет круглых скобок. Подробнее об этом читайте в блоге "вызов методов в JavaScript, не вызывая их на самом деле"
3. Как Генератор
вы могли бы определить функции генератора (с
*), которая возвращает итератор. Вы можете назвать его с помощью распространение синтаксис илиfor...ofсинтаксис.Сначала нам нужен вариант генератора оригинал
greetфункция:function* greet_gen() { console.log('hello'); }и тогда мы называем его без скобок:
[...{ [Symbol.iterator]: greet_gen }];обычно генераторы будут иметь
yieldключевое слово где-то, но оно не требуется для вызова функции.последний оператор вызывает функцию, но это также может быть сделано с деструктурируется:
[,] = { [Symbol.iterator]: greet_gen };или
for ... ofконструкция:for ({} of { [Symbol.iterator]: greet_gen });обратите внимание, что вы можете сделайте выше с оригиналом
greetфункции также, но это вызовет исключение в процессе послеgreetбыл выполнен (протестирован на FF и Chrome). Вы можете управлять исключением с помощьюtry...catchблок.4. Как Добытчик
@jehna1 имеет полный ответ на это, так что дайте ему кредит. Вот способ вызова функции скобках-меньше на глобальном уровне, избегая устаревший
__defineGetter__метод. Он используетObject.definePropertyвместо этого.нам нужно создать вариант оригинала
самый простой способ сделать это с помощью тега
newоператор:function f() { alert('hello'); } new f;хотя это неортодоксально и неестественно, это работает и совершенно законно.
The
newоператор не требует круглых скобок, если параметры не используются.
вы можете использовать геттеры и сеттеры.
var h = { get ello () { alert("World"); } }запустите этот скрипт только с помощью:
h.ello // Fires up alert "world"Edit:
мы даже можем сделать аргументы!
var h = { set ello (what) { alert("Hello " + what); } } h.ello = "world" // Fires up alert "Hello world"Edit 2:
вы можете также определить глобальные функции, которые могут выполняться без скобок:
window.__defineGetter__("hello", function() { alert("world"); }); hello; // Fires up alert "world"и с аргументами:
window.__defineSetter__("hello", function(what) { alert("Hello " + what); }); hello = "world"; // Fires up alert "Hello world"отказ от ответственности:
как заявил @MonkeyZeus: никогда не будет вы используете этот кусок кода в производстве, независимо от того, насколько хороши ваши намерения.
здесь пример для конкретной ситуации:
window.onload = funcRef;хотя это утверждение на самом деле не вызов но приведет к будущее вызов.
но я считаю, что серые области могут быть в порядке для таких загадок:)
если мы принимаем подход латерального мышления, в браузере есть несколько API, которые мы можем использовать для выполнения произвольного JavaScript, включая вызов функции, без каких-либо фактических символов скобок.
1.
locationиjavascript:протокол:один из таких методов заключается в злоупотреблении
javascript:протоколlocationзадание.Пример:
location='javascript:alert\x281\x29'хотя технически
\x28и\x29по-прежнему скобки после того, как код оценивается, фактический(и)символ не появляется. Скобки экранируются в строке JavaScript, которая вычисляется при назначении.
2.
onerrorиeval:аналогично, в зависимости от браузера, мы можем злоупотреблять глобальными
onerror, установив его доeval, и бросая что-то, что будет stringify для допустимого JavaScript. Этот один из них сложнее, потому что браузеры несовместимы в этом поведении, но вот пример для Chrome.рабочий пример для Chrome (не Firefox, другие непроверенные):
window.onerror=eval;Uncaught=0;throw';alert\x281\x29';это работает в Chrome, потому что
throw'test'пройдет'Uncaught test'в качестве первого аргументаonerror, что является почти допустимым JavaScript. Если мы вместоthrow';test'она пройдет'Uncaught ;test'. Теперь у нас есть действительный JavaScript! Просто определитеUncaught, и замените тест на полезную нагрузку.
в заключение:
такой код поистине ужасно и никогда не следует использовать, но иногда используется в атаках XSS, поэтому мораль истории заключается в том, чтобы не полагаться на фильтрующую скобку для предотвращения XSS. Используя CSP чтобы предотвратить такой код также было бы хорошей идеей.
в ES6, у вас есть то, что называется Помеченные Литералы Шаблона.
например:
function foo(val) { console.log(val); } foo`Tagged Template Literals`;
Comments