0

The with() statement is more or less eliminated from modern Javascript. It is not available in strict mode and ES6 modules, TS all that is loaded in strict mode. So what use instead to put unknown variables into a scope?

For example:


function renderTemplateString(template, data) {
    let func
    with(data) {
       func = () => eval('`' + template + '`')
    }
    try {
        return func()
    } catch (error) {
      return `Error in Template ${template}: ${error} in ${JSON.stringify(data)}`
    }
}

console.log(renderTemplateString("foo: ${foo}", {foo: 'bar'}))
// or more realistic:
saveToSearchIndex(templateStringConfigurationOfTheApp, dataFromAnOtherPartOfTheLibrary)

Can the same effect (putting all of data into the scope of eval()) archived without with?

max
  • 27,817
  • 11
  • 50
  • 74
  • eval is a bad choice too. – epascarello Feb 03 '22 at 17:36
  • 1
    "*So what use instead to put unknown variables into a scope?*" - nothing. The solution is not to use unknown variables! – Bergi Feb 03 '22 at 17:44
  • 1
    Actually, the variables in your example are not unknown - it's `foo`, the key of the object that you pass! As soon as you know the variable names, you can inject the code `const foo = data.foo;` into your `eval`uated code. Have a look [here](https://stackoverflow.com/a/24032179/1048572) for a more fancy version of that which is using the `Function` constructor. – Bergi Feb 03 '22 at 17:52
  • Why exactly do you need "unknown variables" to solve the task of "search a string for a known string and replace it with a known value"? – VLAZ Feb 03 '22 at 18:27
  • RE the "more realistic example": if `dataFromAnOtherPartOfTheLibrary` is still an object, then it's still known data, since the keys and values of the object are not a mystery or anything. In what way is it necessary to treat it as "unknown variables" as opposed to using `Object.keys()`, `Object.values()`, `Object.entries()`, `for...in` or any other way to access key/values? – VLAZ Feb 04 '22 at 06:28
  • @VLAZ If I understand your suggestion correctly you are telling me for the specific example above to reimplement ES6 template strings - eg. https://github.com/medikoo/es6-template-strings#readme - I'm aware of that possibility. But my question here is about scope manipulation, the with statements and alternatives to using it. I'm surprised that for a dynamic language like JS there is so little documentation on how to put things into scope. Python's locals() comes to mind. But maybe I just misunderstand you. An alternative implementation of renderTemplateString() would help me understanding. – max Feb 04 '22 at 09:10
  • @max is "reimplement ES6 template strings" *not* what you're trying to do? If it's not then I still don't see *what* you're trying to do that requires scope manipulation. Because you do that using `with` however, `with` is horrible for code quality. What does `with(obj) { foo = 42; }` do? There is no way to know whether you changed a global or not. And `with(obj) { console.log(foo); }` is either a ReferenceError or not. In the extremely vast majority of cases `obj[x] = 42` or `console.log(obj[x])` is what you actually need. What is your task that *cannot* be done without scope manipulation? – VLAZ Feb 04 '22 at 09:18
  • @VLAZ thanks taking your time again to comment. I understand it's essential for you to see my specific use case. My question was asked to better understand the more dynamic parts of Javascript and how they are handled in ES6+. Discussions about `eval`, code quality, maintainability, are all interesting but out of scope (of this question :-) I think Axel Rauschmayers article linked above is a nice summary of that (and alternatives). I had something about `new Function()` in mind but I seem to be unable to provide it with a scope. Python's `eval(expression[, globals[, locals]])` would help... – max Feb 04 '22 at 09:57
  • "*My question was asked to better understand the more dynamic parts of Javascript and how they are handled in ES6+. Discussions about eval, code quality, maintainability, are all interesting but out of scope*" the very reason `with` is being pushed out is about code quality and maintainability. Seems to me you want to replace `with` but avoiding the very reason you are replacing `with`. – VLAZ Feb 04 '22 at 10:06

0 Answers0