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

В каких механизмах Javascript функция Function.prototype.toString не возвращает исходный код этой функции?

EDIT: Чтобы быть явным, я не ищу советов или мнений о качественных достоинствах различных вопросов, связанных с функциональностью, о которой идет речь, и я не ищу надежного решения практической проблемы; Я просто ищу технические, поддающиеся проверке ответы на вопрос в названии. Я добавил вопрос со списком несоответствующих браузеров.

Использование метода .toString обычно будет отображать исходный код для этой функции. Проблема в том, что это поведение не указано - спецификация воздерживается от принятия каких-либо обязательств относительно того, какое поведение должно быть при применении к функциям. Консоль Chrome даже скажет вам (когда вы передаете что-либо, кроме функции Function.toString.call), этот Function.prototype.toString не является общим

В этом сообщении в блоге предлагается, что это можно использовать как метод для создания читаемого синтаксиса для многострочных строк (путем хранения строки в виде многострочного комментария в тело функция no-op). Автор предлагает это использование в контексте написания приложений Node.js с условием, что это поведение является только надежным, поскольку Node.js работает в контролируемой среде, Но в родной сети Javascript все может прийти и интерпретировать его, и мы не должны полагаться на неуказанное поведение.

На практике, однако, я установил скрипку, которая отображает окно выбора, содержимое которого определяется большой многострочной строкой для проверки кода и каждый браузер на моей рабочей станции (Chrome 27, Firefox 21, Opera 12, Safari 5, Internet Explorer 8) выполняется по назначению.

Какие текущие двигатели Javascript не ведут себя следующим образом?

Учитывая, что:

function uncomment(fn){
  return fn.toString().split(/\/\*\n|\n\*\//g).slice(1,-1).join();
}

Следующее:

uncomment(function(){/*
erg
arg
*/});

Должен вывести:

erg
arg

Список несоответствующих браузеров:

  • Firefox 16
  • ...
4b9b3361

Ответ 1

Какие текущие двигатели Javascript не ведут себя таким образом?

Ваш вопрос не совсем определен, учитывая, что вы не определили "популярность". Популярен ли IE6? IE5? IE4? Netscape Navigator? Рысь? Единственный способ ответить на ваш вопрос - перечислить, какие браузеры вы хотите поддержать и проверить. К сожалению, таблица kangax http://kangax.github.io/es5-compat-table/# не тестирует функцию .prototype.toString

Консоль Chrome даже скажет вам (когда вы передаете что-либо, кроме функции o Function.toString.call), что Function.prototype.toString не является общим

указанный в спецификации

спецификация воздерживается от принятия каких-либо обязательств относительно того, какое поведение должно быть при применении к функциям

Требуемое поведение указано в ECMA-262 версии 1 (с 1997 года, http://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%201st%20edition,%20June%201997.pdf). Вы должны преследовать его:

  • http://www.ecma-international.org/ecma-262/5.1/#sec-4.3.24 "... член типа Object, являющийся экземпляром стандартного встроенного конструктора функций и который может быть вызван как подпрограмма"

Из этого мы выводим, что функции являются объектами.

Итак, что такое ToPrimitive?

  • http://www.ecma-international.org/ecma-262/5.1/#sec-9.1 "Значение по умолчанию для объекта извлекается, вызывая внутренний метод [[DefaultValue]] объекта, передавая необязательный подсказку PreferredType."

Итак, нам нужно знать, что делает DefaultValue

Теперь нам просто нужно найти, где описано Function.prototype.toString:

  • http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.4.2 "Возвращаемое по реализации представление функции возвращается. Это представление имеет синтаксис FunctionDeclaration. Обратите внимание, в частности, что использование и размещение пустое пространство, ограничители строк и точки с запятой в представлении Строка зависит от реализации."

Итак, вам гарантировано, что вы получите правильное представление javascript (а не некоторый IL gobbledegook), но не обязательно с комментариями. Например, техника ломается в Firefox 16 (но тогда вы должны спросить, является ли она текущей).

Ответ 2

Итак, Kangax вернулся к теме (заинтригованный, поскольку он был тем, что Angular использует этот хак для основной функциональности в клиентском коде), и составил анализ практики и подготовил тестовую таблицу для состояние декомпиляции функции в Javascript.

Точками вылета являются:

  • Этот метод только удаленно надежен для пользовательских объявлений функций.
  • Некоторые старые мобильные браузеры по-прежнему будут разрушать функциональный код, предположительно по соображениям производительности.
  • Другие старые браузеры покажут оптимизированный код, что-то вроде того, что вы можете получить из Closure Compiler.
  • Другие будут удалять комментарии и изменять пробелы.
  • Internet Explorer будет иногда добавлять комментарии и пробелы вокруг функций.
  • Команда AngularJS, похоже, считает, что этот метод достаточно прочен, чтобы включать в свою библиотеку без явного оговорки. Затем они маркируют (!) Код и переоценивают его (!!).

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

/function\s*[A-Z]/.test( fn )