Angular / Typescript Eval и это - PullRequest
       5

Angular / Typescript Eval и это

0 голосов
/ 11 мая 2018

Так что у меня проблемы с пониманием того, как eval работает с этим в машинописном / угловом написании. Может ли кто-нибудь помочь мне получить здесь работу? Это просто демонстрационная программа, поэтому просто игнорируйте тот факт, что логика не имеет смысла. Я просто хотел бы, чтобы eval обновил динамический массив с динамическим значением.

https://stackblitz.com/edit/angular-pfyt7q?file=src%2Fapp%2Fapp.component.ts

export class AppComponent  {
  arrTest1 = [];
  arrTest2 = [];
  arrTest3 = [];

  constructor() {
    this.TestClass.Run("this.arrTest1 = [1];");
    this.TestClass.Run("this.arrTest2 = [2];");
    this.TestClass.Run("this.arrTest3 = [3];");
    console.log(this.arrTest1);   //Logs: [] (I want: [1])
    console.log(this.arrTest2);   //Logs: [] (I want: [2])
    console.log(this.arrTest3);   //Logs: [] (I want: [3])
  };

  TestClass = {
    Run : (pString) => {
      (0, eval)(pString);
      eval(pString);
    }
  };

}

Ответы [ 3 ]

0 голосов
/ 11 мая 2018

Если вы сделаете что-то вроде:

this.TestClass.call("this");

и в TestCalss:

console.log(eval(pString));

Вы обнаружите, что он регистрируется как объект window.Строка this не берет контекст с собой.Если бы вы зарегистрировались, window.arrTest1, это дало бы вам желаемый результат.

Итак ...

Вам нужно передать контекст:

this.TestClass.Run.call(this, "this.arrTest1 = [1]");

И в вашем TestCalss

TestClass = {
    Run : (pString) => {
      return eval(pString)
    }
};

Почему не работает eval.call (this, pString)?

Есть что-то другое вкак eval() работает.eval() не настоящая функция JavaScript.Как здесь ответили: Как переопределить функцию eval в javascript?

Как вы уже пытались в своем вопросе, вы сделали что-то вроде:

(0, eval)(pString); // this is an indirect call to eval

Что такое косвенныйВызов ??

Согласно ES5, все это косвенные вызовы, и они должны выполнять код в глобальной области видимости

Область видимости gloabl в вашем случае будет ничем, машинописьdefault не предоставляет глобальной области видимости.(Насколько я знаю)

Существует очень подробное описание о eval, написанное здесь: http://perfectionkills.com/global-eval-what-are-the-options/

Согласно приведенной выше ссылке, ниже приведены некоторые примеры косвенных evalзвонки:

(1, eval)('...')
(eval, eval)('...')
(1 ? eval : 0)('...')
(__ = eval)('...')
var e = eval; e('...')
(function(e) { e('...') })(eval)
(function(e) { return e })(eval)('...')
(function() { arguments[0]('...') })(eval)
this.eval('...')
this['eval']('...')
[eval][0]('...')
eval.call(this, '...')  <-- This is your case.
eval('eval')('...')

Еще один абзац из статьи:

Не понимая, что происходит, некоторые люди, к сожалению, придумывают довольно чудовищные решения, такие как eval.call (window, '... '), window.eval.call (window,' ... ') и даже более сложные комбинации.Все это, опять же, не что иное, как косвенные вызовы eval.

Также есть очень хороший параграф, объясняющий, почему (0, eval)(pString) является косвенным.Пожалуйста, посмотрите.К сожалению, я мог найти любую подходящую причину, чтобы объяснить, почему eval.call(this, '...') является косвенным.Возможно, нам придется удовлетворяться утверждением, что eval() не является реальной функцией ().

0 голосов
/ 21 января 2019

У меня была похожая проблема с eval, и в итоге я использовал следующий IIFE.

Выражения приходят из бэкэнда что-то вроде: «Клиент === 123». Нет возможности изменить их.

"eval" не поймет это напрямую. Поскольку в TS переменные-члены доступны с помощью ключевого слова this. Что-то вроде "this.Client" и т. Д.

Один из возможных обходных путей - создать функцию и добавить в нее необходимые переменные, а затем вызвать eval.

  testEval(expression: HTMLInputElement) {
    const result = (() => {
      const Client = this.clientNumber;
      return eval(expression.value);
    })();

    this.expressionResult = `expression: [${expression.value}], result: [${result}]`;
  }

Демонстрация StackBlitz

0 голосов
/ 11 мая 2018

PS: функция eval очень опасна и должна использоваться с осторожностью !!!

Но, поскольку я добрый, я покажу вам, как заставить ваш код работать: чтобы указать контекст вашей функции eval, вы можете использовать функцию вызова javascript, например:

this.TestClass.Run.call(this, "this.arrTest2 = [2];");

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

РЕДАКТИРОВАТЬ: Если вы хотите иметь динамические массивы / значения, вы можете использовать простой объект и динамически добавлять к нему свой атрибут. Допустим, ваш объект A: вы можете использовать A [varName] для динамического создания атрибута объекта.

...