Я неправильно в первом сообщении написал задачу. Там я намного всё упростил, чтобы попонятнее, но вышло наоборот. Пример выше рабочий. У меня же немного иначе это происходит через промисы, примерно так:
Опять же я тут всё сильно упростил. Смысл в том, что у меня в начале, в хедере страницы стоит загрузчик модулей, запускается скрипт и загружает указанные модули создав промис. В конце страницы пользовательские скрипты, которые запускаются в этом промисе после того как страница и все JS модули загружены.
Так вот нужен доступ к переменным промиса при new Function в модуле событий. Опять же мы не можем передавать переменные по цепочке промиса и в модули, т.к. заранее не знаем какие будут вообще переменные.
Теперь я лучше понимаю вашу задачу. Проблема в том, что переменные, объявленные внутри Promise (как aa в вашем примере), находятся в замкнутой области видимости этого Promise и недоступны для функций, создаваемых через new Function() позже.
В JavaScript существует фундаментальное ограничение: функции, созданные через new Function() , имеют доступ только к глобальной области видимости (например, window в браузере), но не к локальным переменным или замыканиям.
Вот несколько возможных подходов к решению:
Хранить все нужные переменные в глобальном объекте (не очень хороший подход с точки зрения архитектуры):
// Создаем глобальный объект для хранения данных window.appContext = {};
new Promise(function(resolve, reject){ // Сохраняем переменную в глобальный объект window.appContext.aa = 'AAA'; resolve('console.log(ee+window.appContext.aa)'); }).then((sf)=>{ function Nf(){ returnnew Function('ee', sf) } let Fu = Nf(); Fu('BBB') })
2. Передавать контекст в виде объекта в обработчики:
new Promise(function(resolve, reject){ let aa = 'AAA'; // Передаем как код, так и данные для выполнения resolve({ code: 'console.log(ee+context.aa)', context: { aa } }); }).then((data)=>{ function Nf(){ // Создаем функцию, которая примет контекст returnnew Function('ee', 'context', data.code) } let Fu = Nf(); Fu('BBB', data.context) })
3. Использовать паттерн "Внедрение зависимостей" для ваших модулей:
// Использование new Promise(function(resolve) { let aa = 'AAA'; // Добавляем aa в контекст ModuleSystem.setContext({ aa }); resolve(); }).then(() => { // Получаем модуль событий с контекстом const events = ModuleSystem.getModule('events');
Ключевое здесь: вместо того, чтобы пытаться передать переменные в функцию напрямую, мы передаем объект контекста, который содержит все нужные переменные.
Это более чистый подход с архитектурной точки зрения, чем использование глобальных переменных.
Ничего не понятно на самом деле =) Но если че то не получается, значит не правильный подход и надо делать по другому, а не городить костыли =)
И на счет глобальных переменных, они получается срабатывают после основного кода?
Да, вы правы - если решение слишком сложное, значит подход стоит пересмотреть. Давайте разберемся в ситуации более четко.
По поводу глобальных переменных - они доступны в любой момент после их объявления. Проблема в том, что когда вы создаете функцию через new Function() , она имеет доступ только к глобальной области видимости, но не к локальной области, где была создана.
В примере:
let aa='AAA', sf='console.log(ee+aa)'; function Nf(){ returnnew Function('ee',sf) } let Fu=Nf(); Fu('BBB')
Переменная aa объявлена в глобальной области, но внутри new Function() она не видна, потому что функция, созданная через new Function() , имеет доступ только к глобальному объекту (window в браузере).
Вот более простой подход без костылей:
// Глобальные переменные должны быть свойствами глобального объекта window.aa = 'AAA'; // Для браузера, если это Node.js, то global.aa = 'AAA'
let sf = 'console.log(ee+aa)';
function Nf(){ returnnew Function('ee', sf) }
let Fu = Nf(); Fu('BBB'); // Теперь должно вывести "BBBAAA"
Главное различие: let aa = 'AAA' создает переменную в текущей области видимости, а window.aa = 'AAA' создает свойство глобального объекта, которое будет доступно внутри функции, созданной через new Function() .
Если хотите проще решить исходную задачу с обработчиками событий, стоит посмотреть в сторону использования системы событий, которая уже решает эту проблему (например, какой-нибудь EventEmitter паттерн).
Я понимаю вашу задачу - вам нужно создавать функции-обработчики событий для элементов с атрибутами, содержащими код, и при этом обеспечить доступ к глобальным переменным.
Проблема в том, что new Function() создает функцию в глобальной области видимости, но не имеет доступа к переменным из областей видимости, в которых она была создана (кроме глобальных).
Вот вариант решения:
// Создаем функцию, которая получит доступ к глобальному объекту function createFunctionWithGlobals(code, paramNames = [], paramValues = []) { // Получаем глобальный объект (window в браузере или global в Node.js) const globalObj = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : this;
// Создаем массив со значениями этих переменных const globalVarValues = globalVarNames.map(name => globalObj[name]);
// Объединяем параметры функции с глобальными переменными const allParamNames = [...paramNames, ...globalVarNames]; const allParamValues = [...paramValues, ...globalVarValues];
// Создаем функцию с доступом к глобальным переменным try { returnnew Function(...allParamNames, code).bind(null, ...allParamValues); } catch (e) { console.error("Ошибка при создании функции:", e); return () => console.error("Функция не была создана из-за ошибки:", e); } }
// Пример использования: let aa = 'AAA'; let sf = 'console.log(ee + aa)';
// Создаем функцию с доступом к глобальным переменным const Fu = createFunctionWithGlobals(sf, ['ee']);
Собирает имена и значения всех подходящих глобальных переменных
Создает функцию, передавая ей как параметры и глобальные переменные, и пользовательские параметры
Это позволит вашим динамически создаваемым обработчикам событий иметь доступ к любым глобальным переменным, которые существуют на момент создания функции.
Я неправильно в первом сообщении написал задачу. Там я намного всё упростил, чтобы попонятнее, но вышло наоборот. Пример выше рабочий. У меня же немного иначе это происходит через промисы, примерно так:
Опять же я тут всё сильно упростил. Смысл в том, что у меня в начале, в хедере страницы стоит загрузчик модулей, запускается скрипт и загружает указанные модули создав промис. В конце страницы пользовательские скрипты, которые запускаются в этом промисе после того как страница и все JS модули загружены.
Так вот нужен доступ к переменным промиса при new Function в модуле событий. Опять же мы не можем передавать переменные по цепочке промиса и в модули, т.к. заранее не знаем какие будут вообще переменные.
Теперь я лучше понимаю вашу задачу. Проблема в том, что переменные, объявленные внутри Promise (как aa в вашем примере), находятся в замкнутой области видимости этого Promise и недоступны для функций, создаваемых через new Function() позже.
В JavaScript существует фундаментальное ограничение: функции, созданные через new Function() , имеют доступ только к глобальной области видимости (например, window в браузере), но не к локальным переменным или замыканиям.
Вот несколько возможных подходов к решению:
2. Передавать контекст в виде объекта в обработчики:
3. Использовать паттерн "Внедрение зависимостей" для ваших модулей:
Ключевое здесь: вместо того, чтобы пытаться передать переменные в функцию напрямую, мы передаем объект контекста, который содержит все нужные переменные.
Это более чистый подход с архитектурной точки зрения, чем использование глобальных переменных.
Ничего не понятно на самом деле =) Но если че то не получается, значит не правильный подход и надо делать по другому, а не городить костыли =)
И на счет глобальных переменных, они получается срабатывают после основного кода?
Да, вы правы - если решение слишком сложное, значит подход стоит пересмотреть. Давайте разберемся в ситуации более четко.
По поводу глобальных переменных - они доступны в любой момент после их объявления. Проблема в том, что когда вы создаете функцию через new Function() , она имеет доступ только к глобальной области видимости, но не к локальной области, где была создана.
В примере:
Переменная aa объявлена в глобальной области, но внутри new Function() она не видна, потому что функция, созданная через new Function() , имеет доступ только к глобальному объекту (window в браузере).
Вот более простой подход без костылей:
Главное различие: let aa = 'AAA' создает переменную в текущей области видимости, а window.aa = 'AAA' создает свойство глобального объекта, которое будет доступно внутри функции, созданной через new Function() .
Если хотите проще решить исходную задачу с обработчиками событий, стоит посмотреть в сторону использования системы событий, которая уже решает эту проблему (например, какой-нибудь EventEmitter паттерн).
Я понимаю вашу задачу - вам нужно создавать функции-обработчики событий для элементов с атрибутами, содержащими код, и при этом обеспечить доступ к глобальным переменным.
Проблема в том, что new Function() создает функцию в глобальной области видимости, но не имеет доступа к переменным из областей видимости, в которых она была создана (кроме глобальных).
Вот вариант решения:
Что делает это решение:
Это позволит вашим динамически создаваемым обработчикам событий иметь доступ к любым глобальным переменным, которые существуют на момент создания функции.
Интересно, вернется ли трафик...
Что за скрипт?))
Самопис 😉
Сделать СДЛ с элементами ГС
Последовал вашему совету😄
https://kakaha.ru/
Покажите источник информации
https://vc.ru/legal/1650856-vlasti-zadumalis-o-vvedenii-sbora-za-reklamu-v-internete-forbes
https://www.forbes.ru/tekhnologii/525011-vlasti-gotovatsa-vvesti-novyj-sbor-za-reklamu-v-internete