最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Issue with with 'use strict' and underscore.js - Stack Overflow

programmeradmin2浏览0评论

I've written an app using Yeoman and backbone.js. At the top of every js file I have specified 'use strict'; and when I run my grunt tasks jshint does not encounter any errors.

I am able to build my app with grunt without issue however when I try to run the uglified js I get the following error:

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

I've searched the code base and the only things using a with statement is underscore.

I'm new to strict mode so I'm not sure how I can resolve this issue. Can I not use strict mode anywhere that I use an underscorejs function?

Thanks.

EDIT:

Given the code samples below (shortened for brevity). How could I change it to resolve this issue.

'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'};
    }
});

in MyView.ejs

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

EDIT 2:

Using @mu is too shorts's answer below I discovered that the best way to resolve the calls to _.template that were giving me grief was change my grunt-JST task as follows:

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

And then change each of my templates to use the <%= data.templateVariable %> format.

May not apply to others, but I ran into this issue using Yeoman with Grunt and a Backbone generator so I can't be the only one.

I've written an app using Yeoman and backbone.js. At the top of every js file I have specified 'use strict'; and when I run my grunt tasks jshint does not encounter any errors.

I am able to build my app with grunt without issue however when I try to run the uglified js I get the following error:

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

I've searched the code base and the only things using a with statement is underscore.

I'm new to strict mode so I'm not sure how I can resolve this issue. Can I not use strict mode anywhere that I use an underscorejs function?

Thanks.

EDIT:

Given the code samples below (shortened for brevity). How could I change it to resolve this issue.

'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'};
    }
});

in MyView.ejs

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

EDIT 2:

Using @mu is too shorts's answer below I discovered that the best way to resolve the calls to _.template that were giving me grief was change my grunt-JST task as follows:

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

And then change each of my templates to use the <%= data.templateVariable %> format.

May not apply to others, but I ran into this issue using Yeoman with Grunt and a Backbone generator so I can't be the only one.

Share Improve this question edited Dec 3, 2014 at 3:58 mu is too short 435k71 gold badges858 silver badges818 bronze badges asked Sep 8, 2013 at 1:09 adampetrieadampetrie 1,1501 gold badge11 silver badges23 bronze badges 3
  • Are you using prepiled Underscore templates somewhere? The only with in Underscore is inside the code that _.template generates so no one should even be aware of with being used unless they're looking at the piled template functions that _.template produces. – mu is too short Commented Sep 8, 2013 at 2:15
  • Just so I understand, you're asking if I'm using under _.template() anywhere? Yes I am. I am assuming then that I need to be more selective with strict mode in that file? – adampetrie Commented Sep 8, 2013 at 2:32
  • @mu is too short - I did some more digging. I am using JST templates throughout the application. The prepiled templates.js uses with statements throughout it. So my question then bees how can I resolve this? If I remove the use strict; directives in the view files that have JST templates and then run grunt --force and ignore the jshint errors, I still get the same end result with the minified js. Thoughts? Thanks. – adampetrie Commented Sep 8, 2013 at 2:54
Add a ment  | 

1 Answer 1

Reset to default 18

Underscore's _.template uses with internally to allow things like <%= pancakes %> to be resolved to obj.pancakes. If you look inside _.template, you'll find this:

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

That's where the offensive with es from. If you're using JST style prepiled templates, that source is what you'll end up with inside your JST object and that makes the withs visible within the scope of "use strict". Notice that settings.variable in there? The documentation says:

By default, template places the values from your data in the local scope via the with statement. However, you can specify a single variable name with the variable setting. This can significantly improve the speed at which a template is able to render.

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

So you can suppress the withs by using the variable option when piling the templates; of course, this also means that you'll have to rewrite all the <%= ... %> parts of your templates to match what the variable option has to say (this should also speed up your templates so it might be worth it just for that).

In your case, you'd change the template to this:

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

and then you'd need to change the _.template call that is used to pile the templates to look like this:

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

You don't have to use data of course, you just need to use the same thing in both the templates and the _.template call.

I don't know how you'd change how your set up calls _.template but it shouldn't be that difficult. I suppose you could monkey patch _.template to have a default value for variable as a last resort.

Here's a simple demo that should illustrate what's going on: http://jsfiddle/ambiguous/Az8QM/


Alternatively, if we look at how "use strict" is scoped, we'll see that:

Strict mode applies to entire scripts or to individual functions.

So you can localize your strictness with something like this:

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

You could also use two JavaScript files instead of just one:

  1. One for your non-template JavaScript with "use strict" enabled.
  2. A second one with just your JST, this one would not "use strict".
发布评论

评论列表(0)

  1. 暂无评论