Javascript/jsLint: What to replace jQuery(this) with when using "use strict";
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开发者_JS百科 };
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.
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.
There is no strict mode violation in your code. If there was, you'd get an Error of some sort.
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
orFunction.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.
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
}
精彩评论