Understanding Eval Reference

大憨熊 提交于 2019-12-25 01:35:51

问题


I know that there are other threads on this topic but I am asking again because I am really trying hard to understand eval and how to use it correctly so that it doesn't become evil. By looking at this code, how can I get the console.log(this.arrTest); to log ['Back to Original']? I tried many variations and none of them work.

I do not want this solution please: this.TestClass.Run.call(this, "this.arrTest = ['Back to Original'];"); I want a solution inside the class level.

Here is an angular blitz to play with: https://stackblitz.com/edit/angular-mtuvvz?file=src%2Fapp%2Fapp.component.ts

export class AppComponent  {
  arrTest = ['Original'];

  constructor() {
    this.TestClass.Run("this.arrTest = ['Back to Original'];");
    console.log(this.arrTest);
  };

  TestClass = {
    Run : (pString) => {
      this.arrTest = ['Changed']; //So this works

      eval(pString); //Why is this not working
      eval.call(this, pString); //Why is this not working
      eval.call(null, pString); //Why is this not working
      (1, eval)(pString); //Why is this not working
      (eval)(pString); //Why is this not working
      var my_eval = eval; //Why is this not working
      my_eval(pString); //Why is this not working
    }
  };

}

I have read both of these articles but I don't understand a solution from them:

http://2ality.com/2014/01/eval.html

http://blog.klipse.tech/javascript/2016/06/20/js-eval-secrets.html


回答1:


There is no way to make eval not 'evil' in this case, because it is evil. An appropriate idiomatic solution should be used instead.

  eval(pString);
  (eval)(pString);

are the ways it's supposed to be workable, they are essentially the same because wrapping eval with parentheses does nothing. The rest of evals are used indirectly, this results in evaluating the code in global scope.

This will work only with ES6 target. It can be seen what the class transpiles to with ES5 target, var _this = this trick is used to pass this from enclosing scope to arrow function. this remains unchanged inside Run method and is TestClass object, not class instance. For this reason

this.TestClass.Run("_this.arrTest = ['Back to Original'];");

will work with ES5 but not ES6 TypeScript target.

This is a good example that shows why eval is considered 'evil'. It results in untyped, unpredictable, unsafe and unoptimized mess that could be avoided by following 'good' coding practices.

It's unclear what are the requirements for TestClass.Run but usually such scenarios are handled with callbacks:

  constructor() {
    this.TestClass.Run(() => {
      this.arrTest = ['Back to Original'];
    });
    console.log(this.arrTest);
  };

  TestClass = {
    Run : (cb: () => void) => {
     // class instance can be passed to callback as an argument
     // or cb.call(this) when needed
      cb();
    }
  };

Depending on what are the reasons to introduce TestClass member to execute code within the class it belongs to, this still may be considered unsuitable solution.




回答2:


So this solves the problem quite well in my scenario:

export class AppComponent  {
  arrTest = ['Original'];

  constructor() {
    this.TestClass.Run("arrTest", "['Back to Original']");
    console.log(this.arrTest);
  };

  TestClass = {
    Run : (pKey, pValue) => {
      this.arrTest = ['Changed']; //So this works

      this[pKey] = pValue;
    }
  };

}


来源:https://stackoverflow.com/questions/50295983/understanding-eval-reference

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!