Convert a string to a template string

前端 未结 19 2147
轮回少年
轮回少年 2020-11-22 08:30

Is it possible to create a template string as a usual string

let a=\"b:${b}\";

an then convert it into a template string

le         


        
相关标签:
19条回答
  • 2020-11-22 09:05

    @Mateusz Moska, solution works great, but when i used it in React Native(build mode), it throws an error: Invalid character '`', though it works when i run it in debug mode.

    So i wrote down my own solution using regex.

    String.prototype.interpolate = function(params) {
      let template = this
      for (let key in params) {
        template = template.replace(new RegExp('\\$\\{' + key + '\\}', 'g'), params[key])
      }
      return template
    }
    
    const template = 'Example text: ${text}',
      result = template.interpolate({
        text: 'Foo Boo'
      })
    
    console.log(result)
    

    Demo: https://es6console.com/j31pqx1p/

    NOTE: Since I don't know the root cause of an issue, i raised a ticket in react-native repo, https://github.com/facebook/react-native/issues/14107, so that once they can able to fix/guide me about the same :)

    0 讨论(0)
  • 2020-11-22 09:09

    What you're asking for here:

    //non working code quoted from the question
    let b=10;
    console.log(a.template());//b:10
    

    is exactly equivalent (in terms of power and, er, safety) to eval: the ability to take a string containing code and execute that code; and also the ability for the executed code to see local variables in the caller's environment.

    There is no way in JS for a function to see local variables in its caller, unless that function is eval(). Even Function() can't do it.


    When you hear there's something called "template strings" coming to JavaScript, it's natural to assume it's a built-in template library, like Mustache. It isn't. It's mainly just string interpolation and multiline strings for JS. I think this is going to be a common misconception for a while, though. :(

    0 讨论(0)
  • 2020-11-22 09:10

    You can use the string prototype, for example

    String.prototype.toTemplate=function(){
        return eval('`'+this+'`');
    }
    //...
    var a="b:${b}";
    var b=10;
    console.log(a.toTemplate());//b:10
    

    But the answer of the original question is no way.

    0 讨论(0)
  • 2020-11-22 09:11

    The issue here is to have a function that has access to the variables of its caller. This is why we see direct eval being used for template processing. A possible solution would be to generate a function taking formal parameters named by a dictionary's properties, and calling it with the corresponding values in the same order. An alternative way would be to have something simple as this:

    var name = "John Smith";
    var message = "Hello, my name is ${name}";
    console.log(new Function('return `' + message + '`;')());
    

    And for anyone using Babel compiler we need to create closure which remembers the environment in which it was created:

    console.log(new Function('name', 'return `' + message + '`;')(name));
    
    0 讨论(0)
  • 2020-11-22 09:11

    I required this method with support for Internet Explorer. It turned out the back ticks aren't supported by even IE11. Also; using eval or it's equivalent Function doesn't feel right.

    For the one that notice; I also use backticks, but these ones are removed by compilers like babel. The methods suggested by other ones, depend on them on run-time. As said before; this is an issue in IE11 and lower.

    So this is what I came up with:

    function get(path, obj, fb = `$\{${path}}`) {
      return path.split('.').reduce((res, key) => res[key] || fb, obj);
    }
    
    function parseTpl(template, map, fallback) {
      return template.replace(/\$\{.+?}/g, (match) => {
        const path = match.substr(2, match.length - 3).trim();
        return get(path, map, fallback);
      });
    }
    

    Example output:

    const data = { person: { name: 'John', age: 18 } };
    
    parseTpl('Hi ${person.name} (${person.age})', data);
    // output: Hi John (18)
    
    parseTpl('Hello ${person.name} from ${person.city}', data);
    // output: Hello John from ${person.city}
    
    parseTpl('Hello ${person.name} from ${person.city}', data, '-');
    // output: Hello John from -
    
    0 讨论(0)
  • 2020-11-22 09:11

    I made my own solution doing a type with a description as a function

    export class Foo {
    ...
    description?: Object;
    ...
    }
    
    let myFoo:Foo = {
    ...
      description: (a,b) => `Welcome ${a}, glad to see you like the ${b} section`.
    ...
    }
    

    and so doing:

    let myDescription = myFoo.description('Bar', 'bar');
    
    0 讨论(0)
提交回复
热议问题