Ответ 1
При синтаксическом анализе кода существует два основных контекста: контекст выражения и контекст оператора. Например, тело функции является контекстом оператора, правая часть присваивания является контекстом выражения. Различать оба имеет смысл запрещать такие вещи, как:
if( if(true) ) alert("nonsense");
Теперь у REPL действительно сложная задача: с одной стороны, они должны анализировать введенные функции и кодовые блоки, а с другой стороны, иногда вы просто хотите проверить, как выглядит определенный объект. Поэтому это:
{ a: 1, b: 2 }
на самом деле это ошибка SyntaxError в JavaScript, так как {
в контексте оператора запускает блок кода, а затем :
недопустим. Однако REPL достаточно умен и помещает этот объект в контекст выражения и оценивает его так, как если бы он был в скобках:
({ a: 1, b: 2 })
то же самое происходит для:
{} == {}
который на самом деле также является SyntaxError, однако REPL также перемещает его в контекст выражения:
({} == {})
Это "перемещение в контекст выражения" является сложной задачей, и кажется, что REPL просто не видит здесь выражения:
{} == null
и поэтому анализирует {}
как блок. Это так, потому что REPL просто наивно проверяет, являются ли первый и последний символ {
и }
, что имеет место для {} == {}
но не для {} == null
.
Соответствующая часть исходного кода хрома:
if (/^\s*\{/.test(text) && /\}\s*$/.test(text))
text = '(' + text + ')';
executionContext.evaluate(text, "console", !!useCommandLineAPI, false, false, true, printResult);