【问题标题】:Javascript/jsLint: What to replace jQuery(this) with when using "use strict";Javascript/jsLint:使用“use strict”时用什么替换jQuery(this);
【发布时间】:2011-11-10 03:07:13
【问题描述】:

当我使用 jslint 验证以下代码时,出现以下错误。

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

第 4 行字符 29 处的问题:严格违反。

 liMegaPosition = jQuery(this).position();  

第 5 行字符 56 处的问题:严格违反。

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

第 6 行字符 12 处的问题:严格违反。

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

第 8 行字符 12 处的问题:严格违反。

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

我猜这是因为使用了 jQuery(this),但我不明白用什么替换它。请注意,这是 not,因为 jQuery 没有被声明为全局。

【问题讨论】:

标签: javascript jquery jslint use-strict


【解决方案1】:

容易多了! 只需使用 ev.currentTarget 而不是这个。和你可以用 ===

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

【讨论】:

    【解决方案2】:

    通过原生 javascript,this 将在 strict mode 中为 undefined,如果函数包含它也未被调用:

    • 作为对象的方法
    • Function.callFunction.apply
    • 作为构造函数

    这就是 jshint 抱怨它的原因。

    但是,如果函数被用作 jQuery 的事件处理程序,jQuery 将强制 $(this) 作为触发事件的 DOM 的 jQuery 对象。

    为了证明这一点,请打开此页面的控制台并运行以下代码。

    (function(){
        "use strict";
        function event_handler() {
            $(this).css('background','red');
        }
    
        $('#content').on('click', 'table', event_handler);
    })();
    

    点击此页面的任何问题或答案,您会看到背景变为红色。

    【讨论】:

      【解决方案3】:

      我认为问题在于您使用this 而不是在方法内部。以下代码

      /*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");
          }
      };
      

      或者这个

      /*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");
      }
      

      不会给你任何错误或警告。

      已更新:另外一个版本非常接近您的原始版本,也没有错误或警告:

      /*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:我觉得这个问题很有意思。所以我浏览了ECMAScript standard。我在“Annex C (informative) The Strict Mode of ECMAScript”中找到了以下内容(请参阅 HTML 版本 here 更好):

      如果在严格模式代码中评估 this,则 this 值为 不强制到一个对象。 nullundefinedthis 值不是 转换为全局对象,原始值不转换 包装对象。通过函数调用传递的 this 值 (包括使用 Function.prototype.applyFunction.prototype.call) 不会强制传递这个值到 对象(10.4.3、11.1.1、15.3.4.3、15.3.4.4)。

      我想这是 JSLint 错误的原因。

      当然,如果您关闭严格模式,代码将不再有错误:

      /*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");
      }
      

      更新 3: 似乎不可能在 function 语句 中使用 this,而在 中使用 this 的可能性函数表达式 似乎很多人都怀疑。今天,我收到了更多关于此的评论。所以我创建了一个非常简单的演示

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

      您可以测试here,在 IE9 中演示显示带有文本“[object Window]”的警报,而在当前版本的 Chrome 和 Firefox 上,您将看到“未定义”。

      所以在函数语句中使用this 的问题不是“jslint 的事情”。这是您在开发 JavaScript 程序时应该考虑的真正问题。

      我个人更喜欢使用函数表达式,几乎从不使用更多函数语句。我认为来自其他程序语言的人(也像我一样)一开始会尝试使用在您最喜欢的语言中很好的相同结构。直到后来才发现块中的变量定义不好(JavaScript 中没有块级范围)并且 函数语句 也不总是最好的选择。

      【讨论】:

      • +1 用于提供安抚 jsLint 的替代方案,我确信这是 OP 所追求的。在回答您在我的回答下的询问时,老实说,我不会花太多时间想知道为什么 jsLint 会这样做,因为我从不使用它。但是关于您引用的规范部分,它仍然不是 jsLint 声称的 “严格违反” 。我想如果 jsLint 无法判断 this 的值是多少,它可能会抱怨您在严格模式下可能会通过 thisundefined 传递给 jQuery(),但调用它仍然有些牵强违反。奇怪的是你的第一个......
      • ...更新您刚刚将函数声明更改为表达式的位置。正在分析的代码没有有效的区别,但它解决了“问题”。这对我来说似乎很奇怪。我当然不会采取删除"use strict"; 声明的方法。我认为如果可能的话,所有代码都应该在严格模式下进行评估。 IMO,严格模式应该很好地取代 jsLint 的有用部分。无论如何,很好的答案。 :)
      • @patrick dw:感谢您的 cmets。我包含了关闭严格模式的示例,只是为了验证 JSLint 的错误消息是否真的存在只是因为使用了严格模式。我个人总是使用“使用严格”。我还永久使用 JSLint 来查找代码中的小错误。我发现 JSLint 非常有帮助,但只发现一些编码风格不好的错误(比如 for (i=0; i<l; i++) 中的“i++”)。我询问您的意见主要是因为我不确定我是否正确解释了 ECMAScript 规范的引用片段。我知道英语不够好。:-)
      • @ChrisFrancis:我是这样理解的:var MyClass = function () { this.myProperty = "smomething"; }; 必须工作因为新对象的构造函数的这种定义(新类定义)。可以使用var myVar = new MyClass(); 来定义调用构造函数的类的实例。问题只是为什么 ECMAScript 的严格模式决定明确删除this 支持。我认为人们希望能够定义与任何对象无关的函数。
      • @ChrisFrancis:不过我看不到太多可能性。如果编写插件并且需要在代码深处调用回调,插件的用户将其作为参数提供,则必须使用usercallback.call(mainObject, parameters) 额外设置this 上下文,这可能对用户有所帮助。用户应该只使用var usercallback = function () 或匿名的回调声明样式,以便能够使用来自this 的信息。长代码内部也存在同样的问题。所以我会继续使用独立于道格拉斯意见的方式。
      【解决方案4】:

      您的代码中没有严格模式违规。如果有,你会得到某种错误。

      【讨论】:

      • 您对我的回答的看法对我来说会很有趣。
      • 在您的回答下回复。 :)
      猜你喜欢
      • 2016-12-15
      • 2013-06-13
      • 2012-05-03
      • 2011-07-10
      • 2018-12-04
      相关资源
      最近更新 更多