В чем разница между void, eval и конструктором Function в JavaScript?

void(document.body.innerText += 'hi')

eval(document.body.innerText +='\nbye')

Function(document.body.innerText += '\n!!!')

void(Function(function foo(){document.body.innerText += '\n>hi2'; return true}).toString())();

eval(Function(function foo(){document.body.innerText += '\nbye2'; return true}).toString())();

Function(Function(function foo(){document.body.innerText += '\n!!!2'; return true}).toString())();

Какова модель обработки для выполнения кода в этих различных операторах?

void(alert('hi'))
undefined

eval(alert('hi'))
undefined

Function(alert('hi'))
function anonymous() {
  undefined
}

eval(Function(function foo(){return true}).toString())();
TypeError: undefined is not a function

void(Function(function foo(){return true}).toString())();
TypeError: string is not a function

Function(Function(function foo(){return true}).toString())();
undefined

3 ответа

Решение

В этой статье eval а также Function Конструкторы объясняются:

(…) Глобальный, встроенный eval Функция оценивает код в области вызова.

Код, выполняемый из функции, созданной Function Конструктор на самом деле не выполняется в глобальном масштабе. Однако он также не выполняется в локальной области, что, вероятно, приводит к путанице. Function Конструктор создает функцию, цепочка областей действия которой состоит из ничего, кроме глобальной области (конечно, с предшествующим собственным объектом активации функции). Любой код, содержащийся в функции, созданной с помощью Function Конструктор оценивает в области действия этой функции, а не в глобальной области. Тем не менее, это почти как если бы код выполнялся глобально, так как глобальный объект - следующий объект в цепочке областей действия.

И согласно этой странице, void просто возвращается undefined:

На многих языках void это тип, который не имеет значений. В JavaScript void это оператор, который принимает операнд и возвращает undefined, Это не полезно, и это очень запутанно. избежать void,

Вот краткое изложение различий оценки:

  • void оценивает код в области действия содержащей функции
  • eval оценивает строки в области действия содержащей функции
  • Function оценивает код в своей области видимости

и обратная разница:

  • void всегда возвращает неопределенное
  • eval возвращает возвращаемое значение выполненного кода
  • Function возвращает анонимную функцию

Рекомендации

Стоит отметить, что вы полностью злоупотребляете этими функциями.

  • void просто оценивает какое-то выражение и возвращает неопределенное.

    Обратите внимание, что это оператор, а не функция, поэтому не нужно заключать оперант в круглые скобки.

    Это полезно только для получения значения undefined, если вы беспокоитесь undefined может быть затенен, или если вы хотите ввести меньше символов.

    Вместо

    var undef = void(document.body.innerText += 'hi')
    

    лучше использовать

    document.body.innerText += 'hi';
    var undef = void 0;
    

    И если вам не нужно быть неопределенным, не используйте void совсем.

  • eval должен вызываться со строкой. Эта строка оценивается как код. Точное поведение зависит от того, вызываете ли вы его в строгом или небрежном режиме, и является ли это прямым или косвенным вызовом.

    Если вы не вызовете его со строкой, он просто вернет аргумент.

    В твоем случае, eval(document.body.innerText += '\nbye') будут:

    1. Бежать document.body.innerText += '\nbye' возвращает новое значение, например "hello\nbye",
    2. Оцените полученный текст как код. Скорее всего, это бросит.

    Я почти уверен eval(document.body.innerText +='\nbye') это не то, что вы хотите, но вот (не рекомендуется) контрпример:

    var myvar = 0;
    var bye = 123
    eval(document.body.innerText += '\nbye');
    console.log(myvar); // 123
    myvar =

  • Function конструктор в основном как eval, но он создает функцию вместо того, чтобы сразу же выполнять оценку строки как кода.

    document.body.innerText += '\n!!!' не может вернуть допустимую строку, поэтому она просто выбросит.

  • Тогда у вас есть несколько странных сочетаний этих функций.

    Если вы передаете функцию Function конструктор, он будет строковым. Function Конструктор вернет анонимную функцию, которая просто объявит функцию как аргумент. Это бессмысленно.

    Если вы позвоните toString, это приведет к строчкам анонимной функции.

    Затем, void(Function(function foo(){document.body.innerText += '\n>hi2'; return true}).toString())(); будет пытаться вызвать эту строку. Но строки не могут быть вызваны. Ошибка.

    А также eval(Function(function foo(){document.body.innerText += '\nbye2'; return true}).toString())(); оценит расслоение. Просто почему? Но объявления функций не возвращают значение, поэтому вы просто получите undefined, который не вызывается. Ошибка.

    А также Function(Function(function foo(){document.body.innerText += '\n!!!2'; return true}).toString())(); будет зачеркнут foo, проанализируйте его для анонимной функции, зафиксируйте анонимную функцию и снова проанализируйте ее для другой анонимной функции. Пожалуйста, не делай этого. Наконец, вызов вернет undefined, потому что там нет оператора return.

Другие вопросы по тегам