search

Home  >  Q&A  >  body text

javascript - 如何为js的eval指定一个object作为上下文?

需要实现一个很简易的js模板.
现在有以下函数:

  function compile(tpl, scope){
    return tpl.replace(/\{\{([\s\S]+?)\}\}/g, function(caught, content){
      var compiled;
      try{
        compiled = eval.call(scope, content);
      }catch(e){
        compiled = caught;
        console.error(e);
      }finally{
        return compiled;
      }
    });
  }

调用compile时
假设tpl为

<p> {{ uploadMaxSize / 1024 / 1024 }}M </p>

以及scope为

{  uploadMaxSize : 1048576  }

而运行结果如下
uploadMaxSize is not defined

这是为何
(另外, 请不要改变论点, 这边的问题是"如何指定一个object作为eval的上下文")

大家讲道理大家讲道理2901 days ago425

reply all(3)I'll reply

  • 黄舟

    黄舟2017-04-10 14:37:10

    于是...

    function compile(tpl, scope){
      return tpl.replace(/\{\{([\s\S]+?)\}\}/g, function(caught, content){
        try{
          return (new Function('with(this){return ' + content + '}')).call(scope);
        }catch(e){
          console.error(e);
          return caught;
        }
      });
    }
    

    strict mode 也可以用with咯

    reply
    0
  • PHP中文网

    PHP中文网2017-04-10 14:37:10

    function compile(tpl, scope) {
      tpl = tpl.replace(/\{%\s*(.*?)\s*%\}/g, function(_, k) {
        for (var i in scope) {
          this[i] = scope[i];
        }
        return eval(k);
      });
      return tpl.replace(/\{\{\s*(.*?)\s*\}\}/g, function(_, k) {
        return scope[k];
      });
    }
    

    应该这样写吧。
    建议把模板填充和模板计算分开。分别用 {{}} 和 {%%}。

    reply
    0
  • 巴扎黑

    巴扎黑2017-04-10 14:37:10

    直接写成:

    compiled = scope[content];
    

    不行吗?
    还有你的模版是不是应该改成:

    <p> {{ uploadMaxSize }}M </p>
    

    reply
    0
  • Cancelreply