By Sarge


2011-09-04 14:55:09 8 Comments

When I validate the following code with jslint I get the following errors.

function displayMegaDropDown() {
"use strict";
var liMegaPosition, divMegaOffset;
liMegaPosition = jQuery(this).position();
divMegaOffset = { top: liMegaPosition.top + jQuery(this).height(), left: liMegaPosition.left };
jQuery(this).find("div").offset(divMegaOffset);

jQuery(this).addClass("hovering");
}

Problem at line 4 character 29: Strict violation.

 liMegaPosition = jQuery(this).position();  

Problem at line 5 character 56: Strict violation.

divMegaOffset = { top: liMegaPosition.top + jQuery(this).height(), left: liM...

Problem at line 6 character 12: Strict violation.

jQuery(this).find("div").offset(divMegaOffset);

Problem at line 8 character 12: Strict violation.

jQuery(this).addClass("hovering");

I'm guessing that it's because of the use of jQuery(this) but I don't understand what to replace it with. Note that this is not because jQuery isn't declared as a global.

4 comments

@zevero 2017-02-25 11:42:39

Much easier! Just use ev.currentTarget instead of this. It is the same as you can test with ===

function event_handler(ev) {
    //var $el = $(this); // jshint - error
    var $el = $(ev.currentTarget); // is exactly the same as above
}

@Malcolm Kee 2017-01-10 13:33:35

By native javascript, this will be undefined in strict mode if the function contains it is not invoked either:

  • as a method of an object
  • by Function.call or Function.apply
  • as a constructor

That's the reason jshint is complaining about it.

However, if the function is being used as a event handler for jQuery, jQuery will force the $(this) as the jQuery object of the DOM that fires the event.

To prove this, open the console of this page and run the following code.

(function(){
    "use strict";
    function event_handler() {
        $(this).css('background','red');
    }

    $('#content').on('click', 'table', event_handler);
})();

Click any question or answer of this page and you would see the background becomes red.

@Oleg 2011-09-04 16:32:27

I think the problem is that you use this not inside of a method. The following code

/*global jQuery */
var myObj = {
    myNethod: function displayMegaDropDown() {
        "use strict";
        var ts = jQuery(this),
            liMegaPosition = ts.position(),
            divMegaOffset = {
                top: liMegaPosition.top + ts.height(),
                left: liMegaPosition.left
            };

        ts.find("div").offset(divMegaOffset);

        ts.addClass("hovering");
    }
};

or this one

/*global jQuery */
function displayMegaDropDown(t) {
    "use strict";
    var ts = jQuery(t),
        liMegaPosition = ts.position(),
        divMegaOffset = {
            top: liMegaPosition.top + ts.height(),
            left: liMegaPosition.left
        };

    ts.find("div").offset(divMegaOffset);

    ts.addClass("hovering");
}

will give you no errors or warnings.

UPDATED: One more version, which is very close to your original one, also has not errors or warnings:

/*global jQuery */
var displayMegaDropDown = function () {
    "use strict";
    var ts = jQuery(this),
        liMegaPosition = ts.position(),
        divMegaOffset = {
            top: liMegaPosition.top + ts.height(),
            left: liMegaPosition.left
        };

    ts.find("div").offset(divMegaOffset);

    ts.addClass("hovering");
};

UPDATED 2: I find the question interesting for understanding. So I look through ECMAScript standard . I find the following in the "Annex C (informative) The Strict Mode of ECMAScript" (see better in HTML version here):

If this is evaluated within strict mode code, then the this value is not coerced to an object. A this value of null or undefined is not converted to the global object and primitive values are not converted to wrapper objects. The this value passed via a function call (including calls made using Function.prototype.apply and Function.prototype.call) do not coerce the passed this value to an object (10.4.3, 11.1.1, 15.3.4.3, 15.3.4.4).

I suppose that it is the reason of the JSLint error.

Of cause if you would switch off the strict mode the code will have no more errors:

/*global jQuery */
/*jslint sloppy: true */
function displayMegaDropDown() {
    var ts = jQuery(this),
        liMegaPosition = ts.position(),
        divMegaOffset = {
            top: liMegaPosition.top + ts.height(),
            left: liMegaPosition.left
        };

    ts.find("div").offset(divMegaOffset);

    ts.addClass("hovering");
}

UPDATED 3: It seems that impossibility of the usage of this in the function statement and the possibility of the usage of this in the function expression seems suspected for many people. Today I received one more comment about this. So I created very simple demo

/*jslint devel: true */
(function () {
    'use strict';
    function test() {
        alert(this);
    }

    test();
}());

You can test it here that in IE9 the demo display alert with the text "[object Window]" and on the current versions of Chrome and Firefox you will see "undefined".

So the problem with the usage of this in function statement is not "a jslint thing". It's real problem which you should take in considerations during development of your JavaScript programs.

I personally prefer to use function expression and almost never use more function statements. I think that the people who come from another program languages (like me too) try at the beginning to use the same construction which was good in your favorite languages. Only later one finds out that definition of variables in block is bad (there are no block level scope in JavaScript) and that function statements is not always the best choice too.

@user113716 2011-09-04 19:31:11

+1 for providing alternatives that appease jsLint, which I'm certain is what OP was after. In response to your inquiry under my answer, I honestly don't spend too much time wondering why jsLint does what it does because I never use it. But with regard to the part of the spec you referenced, it still isn't a "strict violation" as jsLint claims. I suppose if jsLint can't tell what the value of this will be, it could complain that you may be passing undefined to jQuery() via this when in strict mode, but it's still a stretch to call it a violation. The odd thing is with your first...

@user113716 2011-09-04 19:31:34

...update where you just changed the function declaration to an expression. There's no effective difference in the code being analyzed, yet it fixed the "issue". That just seems weird to me. I certainly would not take the approach of removing the "use strict"; declarative. I think all code should be evaluated in strict mode if at all possible. IMO, strict mode should pretty well supplant the useful parts of jsLint. Anyway, good answer. :)

@Oleg 2011-09-04 19:49:53

@patrick dw: Thanks for your comments. I included the example, where the strict mode was off, only to verify that the error message of JSLint exists really only because of the usage strict mode. I personally use "use strict" always. I use also JSLint permanently to find small errors in my code. I find JSLint very helpful, but find only some of errors in style of coding not good (like about "i++" in for (i=0; i<l; i++)). I asked about your opinion mostly because I am not sure that I interpret the referenced fragment of the ECMAScript specification correctly. I know English not good enough.:-)

@Sarge 2011-09-04 23:24:24

After a pile of research I can now see that both @patrick-dw and oleg are correct but oleg's answer appeases jslint. If js calls a method normally, in sloppy mode, then this refers to the global object (the window in a browser). In strict mode this is disabled as oleg pointed out. However, one can call the function with call or apply in order to set this, and event handlers will also set this. For my code, the hoverIntent plugin was calling apply to set this to the element to which the event applied. oleg's update solves the problem but patrick-dw is correct that there is no difference.

@Oleg 2011-09-04 23:31:14

@Sarge: I am glad that I could help you.

@chrisf 2012-04-04 12:59:40

I'm late to the party, but if anyone can explain why a function expression allows "this", but not a function declaration, I'd be pretty interested... :)

@Oleg 2012-04-04 13:20:18

@ChrisFrancis: I understand as so: var MyClass = function () { this.myProperty = "smomething"; }; must work because of such kind of defining of the constructor of the new object (new class definition). One can use var myVar = new MyClass(); to define the instance of the class which call the constructor. The question is only why Strict Mode of ECMAScript decided explicitly remove the this support. I think that one wished to be able to define the function which has no relation to any object.

@chrisf 2012-04-04 13:24:57

Ah ok, thanks! So yeah, because a function expression is syntactically identical to a valid constructor, it must be allowed. That seems like an inherent 'bug' in the Javascript API to me - converting a function declaration to an expression allows you to 'get around' the strict mode violation, without actually changing the context this is evaluated in...

@Oleg 2012-04-04 13:34:07

@ChrisFrancis: Exactly! Last time I used to use var MyClass = function () {} version of definition of the functions because I like to be able to define some context information in this. By the way if you would look through my post here you would find what Douglas Crockford think about this: "Your code is horrible. I wish JSLint rejected all of that". I take it easy and stay at my opinion. :-)

@Oleg 2012-04-04 13:57:29

@ChrisFrancis: Nevertheless I see not so many possibilities. If one writes plugin and one needs to call a callback somewhere deep in the code, which the user of the plugin provides as parameters, one have to use usercallback.call(mainObject, parameters) to set additionally this context which could be helpful for the user. The user should just use var usercallback = function () or anonymous style of declaration of the callback to be able to use information from this. The same problems exist internally in long code. So I 'll continue to use the way independent from the Douglas' opinion.

@Sean McMillan 2012-04-16 19:40:02

My suspicion is that complaining about the use of this in top level functions is a jslint thing, not a strict mode thing.

@Oleg 2012-04-16 20:11:35

@SeanMcMillan: NO, it isn't. I wrote "UPDATED 3" part of my answer specially to answer on your comment.

@Sean McMillan 2012-04-17 15:06:40

@Oleg:But it's legitimate javascript to use this in a function statement. Foolish, sure. Probably not what you want, sure. worth warning about in a lint program, sure. But not an actual error. If it was, then the javascript interpreter would throw an "invalid use of this in a function statement" exception. And it's just as broken in a function expression, it's just that jslint can't tell legit uses from broken uses inside a function expression. Changing from a statement to an expression silences jslint, but does not improve your code any.

@user113716 2011-09-04 15:00:50

There is no strict mode violation in your code. If there was, you'd get an Error of some sort.

@Oleg 2011-09-04 18:48:43

Your opinion about my answer would be interesting for me.

@user113716 2011-09-04 19:33:45

Responded under your answer. :)

Related Questions

Sponsored Content

27 Answered Questions

[SOLVED] What does "use strict" do in JavaScript, and what is the reasoning behind it?

36 Answered Questions

[SOLVED] What is the !! (not not) operator in JavaScript?

  • 2009-04-24 08:13:58
  • Hexagon Theory
  • 517653 View
  • 2957 Score
  • 36 Answer
  • Tags:   javascript operators

25 Answered Questions

[SOLVED] What is the scope of variables in JavaScript?

68 Answered Questions

[SOLVED] What is the most efficient way to deep clone an object in JavaScript?

75 Answered Questions

[SOLVED] What is the JavaScript version of sleep()?

  • 2009-06-04 14:41:10
  • fmsf
  • 2471782 View
  • 2170 Score
  • 75 Answer
  • Tags:   javascript sleep

49 Answered Questions

[SOLVED] Convert form data to JavaScript object with jQuery

14 Answered Questions

[SOLVED] What is the 'new' keyword in JavaScript?

8 Answered Questions

[SOLVED] JSLint is suddenly reporting: Use the function form of "use strict"

  • 2010-12-16 15:36:39
  • Zhami
  • 274410 View
  • 922 Score
  • 8 Answer
  • Tags:   javascript jslint

Sponsored Content