“使用严格”和下划线.js的问题

Issue with with 'use strict' and underscore.js

本文关键字:下划线 js 问题 使用严格      更新时间:2023-09-26

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

我能够毫无问题地使用 grunt 构建我的应用程序,但是当我尝试运行丑陋的 js 时,出现以下错误:

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

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

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

谢谢。

编辑:

给定下面的代码示例(为简洁起见,已缩短)。我如何更改它以解决此问题。

'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 时遇到了这个问题,所以我不能是唯一一个。

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

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

这就是进攻性with的来源。如果您使用的是 JST 样式的预编译模板,则该source就是您最终会在 JST 对象中得到的内容,这使得with"use strict" 范围内可见。注意到settings.variable在那里吗?文档说:

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

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

因此,您可以在编译模板时使用 variable 选项来抑制with;当然,这也意味着您必须重写模板的所有<%= ... %>部分以匹配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"的范围,我们将看到:

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

因此,您可以使用以下内容来本地化您的严格性:

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

你也可以使用两个 JavaScript 文件,而不仅仅是一个:

  1. 一个用于启用了"use strict"的非模板 JavaScript。
  2. 第二个只有你的JST,这个不会"use strict".