Странное регулярное выражение в файле garit.js (автор Джон Резиг) - почему, что и как?

Недавно я использовал небольшую служебную библиотеку Джона Резига, которая называлась наследником.js. Я обычно пытаюсь понять основные части библиотек, которые я использую, и после долгих размышлений я наконец понял сложные фрагменты кода (а именно то, как он мог вызвать соответствующий метод суперкласса).

Бит 1%, который я не получаю, связан с регулярным выражением

fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
  1. Регулярное выражение /xyz/ проверяется на соответствие функции. И MSDN, и MDN утверждают, что test принимает строку в качестве аргумента. Нет упоминания о функции, но, поскольку в консоли нет ошибок, я думаю, она должна летать, но как она работает?
  2. Следующим WTF является то, что тело функции xyz;, Эта функция не может быть выполнена, потому что в противном случае это привело бы к "ReferenceError: xyz is not defined". Верно? Так что же он делает?
  3. Если результат теста верен, то fnTest равен регулярному выражению, которое проверяет _super на границе слова, иначе регулярное выражение, которое совпадает с чем угодно. Двойной WTF; опять как и почему.

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

  // Check if we're overwriting an existing function
  prototype[name] = typeof prop[name] == "function" &&
    typeof _super[name] == "function" && fnTest.test(prop[name])
        ? aFunctionThatCanCallSuper /* Lots of code */
        : prop[name];

Здесь мне интересно, fnTest.test(prop[name]), Я понимаю, что все остальные тесты, которые проверяют, существует ли свойство, являются функцией и т. Д., Но не то, что делает тест регулярного выражения. Кто-нибудь?

1 ответ

Решение

Что?

test принимает только строки в качестве входных данных, поэтому функция будет toStringЭд, как и любой другой объект, который не является строкой. xyz не интерпретируется как переменная, а как строка, поэтому она не выдаст ошибку ссылки. Это происходит и в других местах, например:

var a = function(){}; var b = function(){};
console.log(a + b); // `+` coerces with `toString`

Почему:

Сериализация функций в старых браузерах не надежна и может не выводить _super свойство в теле функции, но (я предполагаю) что-то вроде function{[native code]} или же [object Object]; в этих случаях используйте регулярные выражения, такие как /.*/ сопоставлять что-либо и не выполнять оптимизацию, которую можно выполнить в браузерах, которые выводят правильный результат.

Ссылки по теме для получения дополнительной информации:

http://blog.buymeasoda.com/understanding-john-resigs-simple-javascript-i/ (найдено Андреасом)
http://es5.github.io/x15.3.html
http://bytes.com/topic/javascript/answers/747203-function-tostring

Другие вопросы по тегам