73

Consider this simple code:

"use strict";

var obj = {
    f: function() {
        this.prop = 'value';
        g.bind( this )();
    }
};

function g() {
    console.log( this.prop );
}

If I try to validate this code, jshint gives me the error Possible strict violation. where I call console.log( this.prop );. This is because this is undefined in strict mode in a function.

But I'm binding this function before calling it, so this is the correct object.

I'm using this "design pattern" to avoid cluttering the main object. Passing the properties in the parameters will also clutter the function, so I refuse to do this. Besides, this is exactly what bind is for.

Is there a way for JSHint to let me do this?

danwellman
  • 9,068
  • 8
  • 60
  • 88
Florian Margaine
  • 58,730
  • 15
  • 91
  • 116
  • Is this maybe a bug in jshint? – rlemon Aug 21 '12 at 14:46
  • 1
    Well, it's right in the fact that this is a possible strict violation. However, if it can't parse the `bind` matter, I think it should remain a warning, not an error. Dunno... – Florian Margaine Aug 21 '12 at 14:47
  • 1
    But like you have mentioned; this is not an error ***because*** you have bound it *first* before calling it. Having it spew a warning probably isn't too helpful either because this is the intended purpose of `.bind()` – rlemon Aug 21 '12 at 14:55
  • Yep... I've opened [this issue](https://github.com/jshint/jshint/issues/621) in the jshint queue, but maybe there's a configuration way to change this? That's why I asked the question: to find a workaround (not too ugly), if any is possible. – Florian Margaine Aug 21 '12 at 15:05
  • "this is exactly what `bind` is for" - Well, here, you may want to just do `g.call(this)`, I guess. (Not sure if it solves the issue, though.) If you want to bind `g` by default, you could do `var g = function() { }.bind(obj)` instead, that stops jshint with complaining. – pimvdb Aug 21 '12 at 17:06
  • @pimvdb good idea, but I'm afraid it doesn't play well with hoisting (a good advantage of functions). – Florian Margaine Aug 21 '12 at 17:29
  • In this case, it's obvious what g is bound to. But in general, it can be arbitrarily difficult to determine that, up to the point that it's actually undecidable. I suspect that jshint takes a purposefully simple approach and doesn't try to analyze things that can't be settled by pretty straightforward analysis. – Justin Blank Aug 21 '12 at 19:21
  • @user802500 I suggest you read [this issue](https://github.com/jshint/jshint/issues/621) where one of jshint maintainers is thinking about removing this warning. – Florian Margaine Aug 21 '12 at 19:28

5 Answers5

128

It is extremely hard to detect this case without running the code. You can use option validthis to suppress this warning:

"use strict";

var obj = {
    f: function() {
        this.prop = 'value';
        g.bind( this )();
    }
};

function g() {
    /*jshint validthis:true */
    console.log( this.prop );
}

It is to be noted that jshint comments are function scoped. So the comment will work for the function g and its inner functions, not just the next line.

Florian Margaine
  • 58,730
  • 15
  • 91
  • 116
Anton Kovalyov
  • 2,808
  • 1
  • 22
  • 11
  • Do I have to add this comment before every line where I use `this`? – Florian Margaine Aug 21 '12 at 17:28
  • 1
    No, options in JSHint are function scoped. So this comment will work within function `g` and its inner functions (if any). – Anton Kovalyov Aug 22 '12 at 18:04
  • 9
    But the dumb thing is that it's not a potential strict mode violation. Declaring a var without the var keyword would be a strict mode violation. This is just the wrong warning for an error that might result from attempting to access a property of undefined. It's a potential strict mode-related problem but the problem would have nothing to do with actually violating strict mode rules. – Erik Reppen Aug 22 '12 at 22:39
  • 11
    Or add **"[validthis](http://www.jshint.com/docs/options/#validthis)": true** to your .jshintrc – Raine Revere Feb 21 '14 at 06:32
  • 7
    @Raine this will disable the check for your entire codebase though. This is a special case, and should be handled specifically, not for the whole codebase. – Florian Margaine May 16 '14 at 12:42
  • if you are going to be using this a lot though it may be worth it – Danny Blue Mar 05 '15 at 14:27
7

You can also achieve the same effect if you modify your code to the following to avoid using this all together.

"use strict";

var obj = {
    f: function() {
        this.prop = 'value';
        g.bind( null, this )();
    }
};

function g(self) {
    console.log( self.prop );
}
George
  • 1,552
  • 1
  • 17
  • 26
3

Here's a simpler solution that doesn't require any change of pattern or specific markup for jshint:

"use strict";

var obj = {
    f: function() {
        this.prop = 'value';
        G.bind( this )();
    }
};

function G() {
    console.log( this.prop );
}

jshint assumes that you're following the convention that functions starting with an uppercase letter are classes which will be instantiated and always having this available.

xgrtl
  • 130
  • 1
  • 6
  • 2
    I think that causes quite a code smell. You're just using an unrelated feature of jshint to trick it. – Ben Sep 12 '16 at 12:41
1

Try:

"use strict";

var obj = {
    f: function() {
        this.prop = 'value';
        g.bind( this )();
    }
};

var g = function() {
    console.log( this.prop );
}
Michał Wojas
  • 509
  • 1
  • 5
  • 16
0

This is a different "design pattern" as you put it, it achieves the same thing, but avoids the problem entirely.

"use strict";

function obj() {
    this.prop = '';
}

obj.prototype.f = function obj_f() {
    this.prop = 'value';
    this.g();
};

obj.prototype.g = function obj_g() {
    console.log( this.prop );
};

you would invoke it like thus:

var myO = new obj();
myO.f();
George
  • 1,552
  • 1
  • 17
  • 26