ilyachalov (ilyachalov) wrote,
ilyachalov
ilyachalov

Category:

Учебник по JavaScript: ошибка в примере, eval, use strict

Начало: Учебник по JavaScript: как устроены примеры, движок учебника, Prism.js.

На разбор устройства примеров в учебнике по JavaScript в прошлом посте у меня ушло довольно много времени. Зачем мне это понадобилось? Дело в том, что при запуске первого примера из подраздела 1.1 «Браузерное окружение, спецификации» второй части учебника со страницы самого этого подраздела выдается ошибка: «TypeError: window.sayHi is not a function». Вот код примера:
function sayHi() {
    alert("Hello");
}

// глобальные функции доступны как методы глобального объекта:
window.sayHi();

Я скопировал этот скрипт к себе на компьютер и запустил в браузере. Ошибки не случилось, код отработал так, как предполагалось. Поэтому я и стал разбирать устройство примеров в учебнике, ведь очевидно, что ошибка возникает где-то там.

В результате в прошлом посте я разобрался, как работают примеры в учебнике вообще и как работает данный пример в частности. Запуск кода примера происходит в одной из функций, объявленных в скрипте codeBox.js (см. предыдущий пост). Код примера помещается в переменную runCode, а затем запускается (строка 351 скрипта) вот таким образом:
try {
    window["eval"].call(window, runCode);
} catch (e) {
    alert(e.constructor.name + ": " + e.message);
}

Я решил смоделировать ситуацию у себя на компьютере и написал вот такой код:
"use strict";

let runCode = `
    function sayHi() {
        alert("Hello");
    }

    // глобальные функции доступны как методы глобального объекта:
    window.sayHi();
`

window["eval"].call(window, runCode);

Я включил строгий режим в моем скрипте с помощью "use strict";, потому что в первых подразделах учебника его авторами было оговорено, что все примеры в учебнике запускаются в строгом режиме. Далее я поместил код примера из учебника в переменную runCode, использовав при этом обратные кавычки (по-английски «backticks»), потому что они позволяют легко вводить многострочные литералы. В конце скрипта код примера из учебника запускается с помощью встроенной функции eval.

Этот вариант скрипта у меня тоже запустился без ошибок. Тогда я стал прогонять скрипт codeBox.js на сайте учебника пошагово и заметил, что там строгий режим включается именно для скрипта, помещаемого в переменную runCode. Я изменил моделирующий код своего скрипта следующим образом:

"use strict";

let runCode = `
    "use strict"; // включаем строгий режим внутри runCode
    
    function sayHi() {
        alert("Hello");
    }

    // глобальные функции доступны как методы глобального объекта:
    window.sayHi();
`

window["eval"].call(window, runCode);

И вот уже для такого варианта скрипта получаем искомую ошибку «TypeError: window.sayHi is not a function».

В чем причина ошибки? Дело в том, что без включения строгого режима у eval не будет своего лексического окружения и функция sayHi будет считаться в данном случае глобальной и попадет в глобальный объект window, откуда ее можно будет вызвать указанным способом — window.sayHi();.

Если же в скрипте, передаваемом на исполнение функции eval, будет включен строгий режим, у eval будет своё лексическое окружение, функция sayHi будет считаться локальной, а не глобальной, и поэтому она не попадет в глобальный объект window, а потому обращение к ней через этот объект window.sayHi(); приведет к ошибке «TypeError: window.sayHi is not a function» (то есть по-русски: «Функции sayHi в объекте window не существует»).

В принципе, об этом было рассказано в подразделе 14.2 «Eval: выполнение строки кода» учебника.

Также об этом упомянуто в следующей большой статье, посвященной строгому режиму:
https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Strict_mode

Авторы учебника могут исправить эту ошибку, к примеру, передав скрипт в переменной runCode для исполнения функцией eval без включения в скрипте строгого режима.
Tags: Образование, Программирование, Сайтостроение
Subscribe

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 0 comments