Странное регулярное выражение в файле garit.js (автор Джон Резиг) - почему, что и как?
Недавно я использовал небольшую служебную библиотеку Джона Резига, которая называлась наследником.js. Я обычно пытаюсь понять основные части библиотек, которые я использую, и после долгих размышлений я наконец понял сложные фрагменты кода (а именно то, как он мог вызвать соответствующий метод суперкласса).
Бит 1%, который я не получаю, связан с регулярным выражением
fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
- Регулярное выражение /xyz/ проверяется на соответствие функции. И MSDN, и MDN утверждают, что
test
принимает строку в качестве аргумента. Нет упоминания о функции, но, поскольку в консоли нет ошибок, я думаю, она должна летать, но как она работает? - Следующим WTF является то, что тело функции
xyz;
, Эта функция не может быть выполнена, потому что в противном случае это привело бы к "ReferenceError: xyz is not defined
". Верно? Так что же он делает? - Если результат теста верен, то
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