8

我使用 Yeoman 和backbone.js 编写了一个应用程序。在我指定的每个 js 文件的顶部,'use strict';当我运行我的 grunt 任务时,jshint 没有遇到任何错误。

我可以毫无问题地使用 grunt 构建我的应用程序,但是当我尝试运行 uglified js 时,我收到以下错误:

Uncaught SyntaxError: Strict mode code may not include a with statement

我搜索了代码库,唯一使用 with 语句的东西是下划线。

我是严格模式的新手,所以我不确定如何解决这个问题。我不能在使用 underscorejs 函数的任何地方使用严格模式吗?

谢谢。

编辑:

给定下面的代码示例(为简洁而缩短)。我怎么能改变它来解决这个问题。

'use strict';

/*global, Backbone, JST*/

var MyView = Backbone.View.extend({

    template: JST['app/scripts/templates/MyView.ejs'],

    initialize: function()
    {
        this.render();
    },

    render : function()
    {
        this.$el.html(this.template(this.templateVariables()));
        return this;
    },

    templateVariables: function()
    {
        return {var1 : 'Hello', var2 : 'World'};
    }
});

在 MyView.ejs

<p><%= var1 %><%= var2 %>!</p> //<p>Hello World!</p>

编辑2:

在下面使用@mu 太短的答案我发现解决对 _.template 的调用让我感到悲伤的最佳方法是更改​​我的 grunt-JST 任务,如下所示:

jst: {
        compile: {
            options:
            {
                templateSettings:
                {
                    variable: 'data'
                }
            },
            files: {
                '.tmp/scripts/templates.js': ['<%= yeoman.app %>/scripts/templates/*.ejs']
            }
        }
    },

然后更改我的每个模板以使用该<%= data.templateVariable %>格式。

可能不适用于其他人,但我在使用带有 Grunt 和 Backbone 生成器的 Yeoman 时遇到了这个问题,所以我不能成为唯一的人。

4

1 回答 1

18

Underscore 在内部_.template使用with以允许将之类的事情<%= pancakes %>解析为obj.pancakes. 如果你往里面看_.template,你会发现:

if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';

这就是进攻的with来源。如果您使用的是 JST 样式的预编译模板,那么这source就是您最终会在JST对象内部得到的内容,这会使withs 在"use strict". 注意到settings.variable里面了吗?文档说:

默认情况下,模板with通过语句将数据中的值放在本地范围内。但是,您可以使用变量设置指定单个变量名称。这可以显着提高模板的渲染速度。

_.template("Using 'with': <%= data.answer %>", {answer: 'no'}, {variable: 'data'});
=> "Using 'with': no"

因此,您可以在编译模板时with使用该选项来抑制s;variable当然,这也意味着您必须重写<%= ... %>模板的所有部分以匹配variable选项必须说的内容(这也应该加快您的模板速度,因此可能值得这样做)。

在您的情况下,您可以将模板更改为:

<p><%= data.var1 %><%= data.var2 %>!</p> //<p>Hello World!</p>

然后您需要将_.template用于编译模板的调用更改为如下所示:

var compiled_template = _.template(raw_template, null, { variable: 'data' });

data当然不必使用,您只需要在模板和_.template调用中使用相同的东西。

我不知道你会如何改变你的设置调用_.template方式,但这不应该那么困难。我想你可以猴子补丁作为最后的手段_.template使用默认值。variable

这是一个简单的演示,应该说明发生了什么:http: //jsfiddle.net/ambiguous/Az8QM/


或者,如果我们查看"use strict"is scoped的方式,我们会看到:

严格模式适用于整个脚本单个函数

因此,您可以通过以下方式本地化您的严格性:

(function() {
    "use strict";
    // All your non-JST JavaScript goes here.
})();
// Append your JST out here.

您还可以使用两个 JavaScript 文件而不是一个:

  1. 一种用于启用的非模板 JavaScript "use strict"
  2. 第二个只有你的JST,这个不会 "use strict"
于 2013-09-08T03:24:56.437 回答