【问题标题】:4 different scenarios of 'this'. What's the correct interpretation?'this' 的 4 种不同场景。正确的解释是什么?
【发布时间】:2012-04-24 08:18:18
【问题描述】:

这些来自 tuts-premium Jquery vid tutorials。
http://tutsplus.com/lesson/the-this-keyword/ Jeff 每次都会解释“this”指的是什么,但我不确定我是否掌握了所有这些背后的原因。

例如1

function doSomething(e) { 
e.preventDefault(); 
console.log(this);
} 

$('a').on('click', doSomething);

在这种情况下,“this 指的是 'a' 元素”(在这种情况下是父对象)

我猜那是因为这里的语句等同于:

$('a').on('click', function (e) { 
    e.preventDefault(); 
    console.log(this);
    } 

所以'a'是父对象

例如2

var obj = { 
    doIt: function(e){ 
    e.preventDefault(); 
    console.log(this);
    }
}

$('a').on('click',  obj.doIt);

在这种情况下,“this 仍然指的是 'a' 元素”(*但显然它不是父对象?)

似乎这次我们调用了一个方法,但该语句仍然等同于 E.g. 1

*教程中的一件事让我有点困惑。我认为'this'总是指父对象,所以在这种情况下'a'仍然是父对象。但是(在本教程中的 05.23 处)他推断情况并非如此,并指出“有时您可能希望 'this' 引用它的父对象,这将是 'obj'”,在这种情况下,他创建了例如 3.

例如3

var obj = { 
    doIt: function(){ 
    console.log(this);
    }
}

$('a').on('click',  function(e){    
obj.doIt(); 
        };
e.preventDefault(); 

在这种情况下,“this 指的是 obj 对象”

我认为这是因为“this”在嵌套函数中,因为该语句等同于:

$('a').on('click',  function(){    
function(){ console.log(this);}
};
e.preventDefault(); 

我真的不明白为什么,特别是当我在一篇文章中读到嵌套函数“this”“迷失方向并引用头对象(窗口对象)”时。

例如4

var obj = { 
    doIt: function(){ 
    console.log(this);     
    }
}

$('a').on('click',  function(e){    
       obj.doIt.call(this);             
       e.preventDefault(); 
});

在这种情况下“这指的是'a'”

根据 Javascript Definitive Guide “call() 的第一个参数是调用函数的对象” 这里“this”用作第一个参数。但是“this”不是要在其上调用函数的对象??
我想我知道调用函数是用来调用函数并将其第一个参数用作指向不同对象的指针,但我不明白为什么使用“this”意味着函数被“a”调用。这也不是我在其他 call() 示例中看到的。

很抱歉发布了如此庞大的帖子。希望这个阶段有人还在阅读……

【问题讨论】:

  • +1 因为我现在开始回答这个出色的问题为时已晚。毫无疑问,其他人很快就会 - 这是一个关键点,而且在 JS 教程中通常很少涉及。
  • “我认为 'this' 总是指父对象...” 不,不要将this 视为父对象。把它想象成一个调用上下文,它的值可以用几种不同的方式设置,其中一种恰好是从一个对象调用一个方法。

标签: jquery call this


【解决方案1】:

我希望这有助于澄清问题,它确实会让人感到困惑。

  • this 在您的代码中松散时,它将引用全局对象(在网络浏览器中,即window)。

    console.log(this); // window
    
  • this 在对象方法中时(例如在您的 E.g. 3 中),它将引用该对象。这适用于使用new 实例化的对象,或作为对象文字(如您的示例)。

     var obj = { 
         doIt: function(e){ 
             console.log(this);
         }
     }
     obj.doIt(); // obj
    
  • 在事件处理程序中,this 将引用事件绑定到的对象。

    // This is the plain js equivalent of your jQuery example
    document.getElementsByTagName['a'][0].addEventListener('click', function(e){
        console.log(this); // the first anchor on the document
    });
    
    // This is exactly the same:
    var clickHandler = function(e){
        console.log(this); // the first anchor on the document
    };
    document.getElementsByTagName['a'][0].addEventListener('click', clickHandler); 
    
    // Even if the handler is defined inside of another object, this will be
    // the obj the event is bound to. It's the case of your E.g. 2
    var obj = { 
        doIt: function(e){  
            console.log(this); // the first anchor on the document
        }
    }
    document.getElementsByTagName['a'][0].addEventListener('click', obj.doIt);
    // When you pass obj.doIt to addEventListener above, you are passing a reference
    // to that function. It's like "stealing" the function from the object
    
  • 当一个对象作为第一个参数传递给Function.callFunction.apply 时,如果this 出现在函数内部,它将引用您传递的对象。这是一种强制 this 指向的内容的方法。

    var obj = { 
        doIt: function(){ 
            console.log(this); // window 
        }
    }
    obj.doIt.call(window);
    

【讨论】:

  • 但是,给定objdoIt 函数,如果我们使用var fn = obj.doIt; fn()this 将在fn 内部引用window
  • 是的,就像我在 addEventListener 的示例中一样(除了在这种情况下它将指向一个 DOM 节点,而不是 window)。但逻辑是一样的。
【解决方案2】:

非常感谢这些回复。我在凌晨发布并尝试(并且需要)花一些时间来消化您的反馈。

https://developer.mozilla.org/en/JavaScript/Reference/Operators/this 真是太棒了。我已经阅读了相当多的文章/tuts,而这一篇似乎是更好的一篇。

我认为主要的启示是绑定到“this”的对象取决于函数的调用方式/位置(调用上下文),而不是函数的定义方式或位置。

所以只是回到问答范围,并尝试根据你们的回答来回答我自己的问题……

例如1 这里:“doSomething”函数在点击处理程序的上下文中被调用,所以绑定到“this”的对象是“a”

例如2 再次单击处理程序仍在触发该函数,因此绑定到“this”的对象是“a”

例如3 在嵌套函数中,调用上下文是 obj.doIt()。因此,正如他在教程中所说,绑定到“this”的对象是“obj”。

尽管基于以下 developer.mozilla.org 示例中的类似逻辑,该对象不是真正绑定到“obj.doIt”:

o.b = {g: independent, prop: 42};  
console.log(o.b.g()); // logs 42  

" this 绑定仅受最直接的成员引用影响……。函数内部的 this 将引用 ob 对象本身是 o 的成员这一事实没有任何后果;最直接的引用才是最重要的。 "

例如4

这里 - 'call' 的工作是间接调用函数,就好像它是一个新对象的方法 - 在这种情况下,我们定义为 'this'。这里的“this”指的是“a”,因为它是由点击处理程序触发的函数的一部分。

我希望这更接近一点。在这方面我觉得自己像个傻瓜(可怕的双关语),因为答案正在呈现给我,但我仍然不完全相信我已经掌握了这个概念。

如果我必须爬回我的洞一段时间来消化,我恳求 newby 状态,现在只用几周的时间在 Javascript 和 JQuery 上崩溃。

再次感谢大家的反馈。

【讨论】:

    【解决方案3】:

    this 在 JavaScript 中的行为方式起初有点令人困惑。基本上,与变量(静态作用域)不同,this动态 作用域的。也就是说,this 的值取决于您调用函数的位置,而不是您编写函数的位置。

    当您将函数传递给on 时,稍后会从this 是相关元素的上下文中调用它。 无论你如何获得该功能,都会发生这种情况。也就是说,一个函数并不关心你是使用obj.fn这样的语法访问它,还是只关心它的名字fn——无论哪种情况,表达式的值都是一样的。

    对于函数以外的东西,这是有道理的。给定:

    var a   = 10,
        obj = { a : 10 };
    

    您会同意表达式aobj.a 具有相同的值。函数也是如此。

    简而言之:this 的值取决于您调用函数的位置和方式,而不是您声明它的方式和位置,或者在调用它之前如何引用它。

    【讨论】:

    • 我们不应该将this 与“范围”混淆。它们是完全分开的。而this 不是由where 决定的,而是由如何 调用函数来决定的。
    • 仔细一看,有几处不对。就像... “...它稍后会从上下文中调用,其中这是有问题的元素”。这没什么区别。除非您使用.call().apply() 手动传输封闭上下文,否则不会将封闭上下文传输到调用的上下文。而这个... "...一个函数并不关心您是使用obj.fn 之类的语法访问它,还是只使用它的名称fn" ...也不正确。这非常重要。
    • 我的意思是表达式fobj.f 具有相同的值(只要fobj.f 指向相同的函数)。也许我对此不够清楚。至于另一点,您可以通过将函数放入对象中来更改this 的值而不使用callapply。因此,无论您是从对象中调用它还是单独调用它都很重要,但对于仅访问它(将函数作为值获取)并不重要。
    • 是的,但这意味着它取决于您 如何 引用它,这与您的最后一句话相矛盾 "this 取决于您调用函数的位置而不是......你如何引用它。” 是的,你可以更改this,没有.call().apply(),但正如我所说,你不能转移 i> 没有它们的被调用函数的封闭上下文,除非this 恰好是同一个对象。
    • 嗯,最后一句话似乎是错误的。我的意思是 this 取决于您调用函数的方式和位置,而不是您之前引用它的方式或声明它的方式和位置。我必须更新它。
    【解决方案4】:

    https://developer.mozilla.org/en/JavaScript/Reference/Operators/this 是对this 关键字的简短介绍。并查看call() 的参考。

    作为 jQuery 调用(是的,使用 .call() 方法)在 dom 元素上下文中的事件处理程序,您的所有示例都得到了解释。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多