Использование косвенных вызовов eval
Доступ к глобальным определениям const
и let
можно осуществить с помощью косвенного вызова eval
. То есть сделать eval
результатом выражения, разделенного запятыми, или сначала присвоить его переменной. Если синтаксический доступ осуществляется не напрямую к встроенной функции eval
, это косвенный доступ, а косвенный доступ выполняется в глобальной области видимости.
Вы также можете установить глобальные let
переменные, создав скрипт для выполнения операции настройки.
"use strict";
let myVar = "global variable myVar";
console.log( myVar);
(function myLibrary() {
const myVar = "local variable myVar";
const indirectEval = eval;
var varName = "myVar";
console.log( eval(varName)); // direct call uses local scope
console.log( indirectEval(varName)); // indirect call uses global scope
var result = "\"updated global variable even though shadowed\"";
var js = varName + '=' + result;
indirectEval(js);
// but trying to define a new let variable doesn't attach to global scope
var js2 ='let letVar2 = "let variable two"';
indirectEval( js2);
})();
console.log( myVar)
console.log( "letVar2: " + typeof letVar2);
Чего вы не можете сделать, так это добавить переменную let
или const
в глобальную область видимости, используя косвенный вызов eval: они являются объявлениями уровня блока, а код, который оценивает eval
, считается блоком, поэтому объявления отбрасываются, когда (косвенный вызов) eval
возвращается.
PS. Это технический ответ. И да, я уже слышал, что «eval — это зло», один или три раза.
Для доступа только для чтения с использованием жестко закодированных строк имен переменных (для предотвращения вставки кода) вы можете использовать шаблон:
(0,eval)("identifierString");
как например:
var x = 3;
const y = 7;
let z = 21;
{
const y = "shadow"
let z = 42;
console.log('x = ' + (0,eval)('x')); //x = 3
console.log('y = ' + (0,eval)('y')); //y = 7
console.log('z = ' + (0,eval)('z')); //z = 21
}
Косвенные и прямые звонки на eval
Прямой вызов eval
получает только те значения глобальных переменных, которые не были затенены в области действия вызова. Это может ограничить выбор имен переменных или того, откуда можно сделать вызов в библиотеке.
Косвенный вызов выполняется в глобальной области и может получать значения глобальных переменных независимо от затенения имен в библиотеке.
Создание нового объекта Function
из исходного текста и его вызов могут стать альтернативой использованию косвенного вызова eval
на веб-странице. Однако разница в основном семантическая, а не одна лучше другой.
вопросы
Если имя глобальной переменной (var
, let
, const
или идентификатор class
) поступает из пользовательского ввода, его действительно следует проверять на достоверность (не все это easy) или, по крайней мере, доступ в блоке try/catch для перехвата использования необъявленных идентификаторов или использования объявлений имен перед инициализацией.
Лично я бы порекомендовал найти альтернативу использованию строк имен глобальных переменных в целом. На ум приходит предоставление статического объекта пространства имен в библиотеке (например, myLibrary.data
) и обработка строковых значений, которые являются именами свойств объекта, или включение параметров объекта option в вызовы библиотеки.
person
traktor
schedule
01.05.2018
window.y
иwindow.z
- мне кажется, это та же проблема? - person CertainPerformance   schedule 01.05.2018eval
, но предполагаемый дубликат даже не упоминаетeval
(в вопросе или любом из ответов). Понятно, что некоторые люди думали, что на этот вопрос нет ответа. - person Dem Pilafian   schedule 01.05.2018