Является ли это подходящим случаем, когда использование создания динамических функций было бы оправданным?
В настоящее время я занимаюсь разработкой учебного сайта для обучения основам веб-разработки (HTML, CSS и JavaScript, для начинающих). Мне нужна установка, в которой я мог бы подробно рассказать обо всех видах тем, а затем предоставить базовую среду для песочницы, где пользователь мог бы написать код, который решает вопрос, заданный в конце каждого учебного раздела.
Например, если бы я рассмотрел умножение в предыдущем уроке, а пользователь только что закончил урок о функциях, способных возвращать значения, я мог бы попросить, чтобы они отправили функцию, которая возвращает произведение двух параметров.
Разве это не идеальный пример, в котором использование создания динамических функций будет считаться хорошей идеей? Давайте посмотрим на пример.
<script>
function check()
{
eval('var f = ' + document.getElementById('user_code').value);
if (f(5, 10) == 50)
{
// user properly wrote a function which
// returned the product of its parameters
}
}
</script>
Это вообще плохая идея? Если так, пожалуйста, объясните.
5 ответов
Похоже, это может сработать. Однако самой большой проблемой в вашей среде может быть обработка ошибок. Студенты обязательно сделают все виды ошибок:
- Ошибки времени компиляции, которые будут обнаружены в
eval()
- Ошибки времени выполнения, которые будут обнаружены при вызове функции
- Неопределяемые ошибки времени выполнения, такие как бесконечный цикл или переполнение стека
Более сложный подход может проанализировать введенный Javascript в представлении дерева разбора, а затем сравнить его с ожидаемым деревом разбора. Если он не совпадает, укажите, что может быть не так, и попросите ученика повторить попытку. Если оно совпадает, то вы можете eval()
и вызвать функцию, зная, что она будет делать то, что вы ожидаете.
Реализация лексера и парсера для Javascript в Javascript будет сложной, но, безусловно, не невозможной.
Похоже, вы хотите переделать Firebug или даже новые инструменты разработчика в IE8. В связи с этим я должен сказать, что никогда не бывает полезного случая. Не говоря уже о возможностях внедрения скриптов, если этот сайт станет публичным.
Должно работать, пока вы работаете в закрытой среде. Eval открывает вам возможности для атак с использованием кода, поэтому я бы не стал размещать это на общедоступном веб-сайте, но если он полностью содержится в вашей аудитории, с вами все будет в порядке.
Код будет работать, но что если возникнет ошибка как синтаксическая, так и иначе? Возможно, использование блока try для обнаружения любой ошибки и ее отображения пользователю поможет немного...
Не уверен, что это поможет.
В твоем случае я чувствую, что в этом нет ничего плохого. В качестве альтернативы вы можете запустить код с помощью new Function()
сначала собрать материал, а затем запустить его. Теоретически это разделило бы этапы "компиляции" и выполнения. тем не мение eval
сначала проверим код и все равно выдам ошибки:
var usercode = document.getElementById('user_code').value;
try {
var f = new Function( 'a','b','return (' + usercode + ')(a,b);' );
if ( f( 5, 10 ) ) {
// user properly wrote a function which
// returned the product of its parameters
}
else {
// user wrote code that ran but produced incorrect results
}
}
catch ( ex ) {
// user wrote something really bad
}
Проблема с такими действиями заключается в том, что создаваемые исключения могут быть бессмысленными. "foo;;=bar"
сообщит об ошибке "отсутствует" в скобках, в то время как eval выдаст ошибку синтаксиса пропппера. Вы можете обойти это, (regexp), сначала извлекая параметры и тело из пользовательского кода, а затем собирая его. Но тогда, как это было бы лучше, чем eval
?
Я думаю, что ваша настоящая проблема будет помогать пользователям избежать ловушек неявных глобальных переменных. Как вы собираетесь помочь пользователям избежать написания кода, который работает только во второй раз, потому что глобальный был установлен в первый раз? Вам не нужно будет внедрять чистую песочницу каждый раз? Я хотел бы взглянуть на то, как jsbin.com, firebug и подобные инструменты справляются с этими вещами.
Я чувствую, что вы должны пойти с eval
сейчас и поменяйте его на более сложный материал позже, если возникнет необходимость.