jQuery中的“this”是什么意思?

55

在jquery中,this代表什么,以及它在何时使用?


1
当前元素... 例如 <input type="text" onclick="this.value='abcde'" value="" />当您单击它时,此文本框将包含 abcde... - Oliver M Grech
14
在JavaScript中,“this”的概念是最复杂的主题之一。如果你想要使用JavaScript很多,我强烈建议你仔细阅读相关内容。当你认为你理解了这个概念时,请再次回来阅读它,因为如果你像我一样,第一次认为自己理解了,实际上并没有真正理解。 - Matt
相关链接:https://dev59.com/1nVC5IYBdhLWcg3w9GLM - Ciro Santilli OurBigBook.com
@Matt,是的,你说得对:) 我们都是过于自信的人。 - Bimal Das
这里解释了 JavaScript 中 this 的概念:https://scotch.io/@alZami/understanding-this-in-javascript。 - AL-zami
6个回答

96

this在JavaScript中非常特殊和强大。它可以意味着几乎任何东西。我在这里这里涵盖了一些内容,但真的值得找一个好的JavaScript教程并花点时间学习。

让我们先看看jQuery的使用,然后再更普遍地讨论JavaScript(稍微)。

具体来说是在jQuery中

在使用jQuery编写的代码中,this通常指调用函数的DOM元素(例如,在事件回调中)。

示例jQuery事件回调(关于this是什么在.bind文档中有介绍):

$("div").click(function() {
    // Here, `this` will be the DOM element for the div that was clicked,
    // so you could (for instance) set its foreground color:
    this.style.color = "red";

    // You'll frequently see $(this) used to wrap a jQuery object around the
    // element, because jQuery makes lots of things a lot simpler. You might
    // hide the element, for example:
    $(this).hide();
});

同样,各种jQuery函数可以作用于当前jQuery选择器匹配的所有元素,并可选地接受一个函数,当该函数被调用时,this再次成为相关的DOM元素,例如,html函数允许这样做:

// Find all divs inside the `foo` element, and set
// their content to their CSS class name(s)
// (Okay, so it's a hokey example)
$("#foo div").html(function() {
    return this.className;
});

jQuery.each的回调函数中,jQuery还会使用this

var a = ["one", "two", "three"];
jQuery.each(a, function() {
    alert(this);
});

...这将会触发 "one",然后是 "two",最后是 "three"。正如你所看到的,这是一种完全不同的使用方式 this

(令人困惑的是,jQuery 有两个名为 each 的函数,上面那个是在 jQuery/$ 函数本身上的,并且总是以这种方式调用 [jQuery.each(...)$.each(...)],而不是在 jQuery 实例 [对象] 上的另一个不同的函数。这里是其他函数的文档,我在这个答案中不讨论其他函数,因为它与 html 和事件回调使用相同的 this,而我想展示 jQuery 对 this 的一个不同的用法。)

在 JavaScript 中通用

this 指的是一个对象。 更新:自 ES5 的严格模式起,这就不再正确了,this 可以有任何值。在任何给定的函数调用中,this 的值由函数被调用的方式确定(而不是函数定义的位置,如 C# 或 Java 等语言)。调用函数时设置 this 最常见的方法是通过对象上的属性调用函数:

var obj = {};
obj.foo = function() {
    alert(this.firstName);
};
obj.firstName = "Fred";
obj.foo(); // alerts "Fred"

因为我们通过obj的属性调用了foo,所以在调用期间this被设置为obj。但是不要认为fooobj有任何关联,这也可以正常工作:

var obj = {};
obj.foo = function() {
    alert(this.firstName);
};
obj.firstName = "Fred";
obj.foo(); // alerts "Fred"

var differentObj = {};
differentObj.firstName = "Barney";
differentObj.bar = obj.foo; // Not *calling* it, just getting a reference to it
differentObj.bar(); // alerts "Barney"

事实上,foo并没有与任何对象紧密相连:
var f = obj.foo; // Not *calling* it, just getting a reference to it
f(); // Probably alerts "undefined"

由于我们没有通过对象属性调用f,因此this没有被明确设置。当this没有被明确设置时,默认为全局对象(在浏览器中为window)。window可能没有一个firstName属性,因此我们在警报中得到了"undefined"。

还有其他调用函数和设置this的方法:使用函数的.call.apply函数:

function foo(arg1, arg2) {
    alert(this.firstName);
    alert(arg1);
    alert(arg2);
}

var obj = {firstName: "Wilma"};
foo.call(obj, 42, 27); // alerts "Wilma", "42", and "27"

call会将第一个参数设置为函数内部的this,然后将其他参数传递给被调用的函数。

applycall相同,但你需要将函数的参数以数组的形式传递。

var obj = {firstName: "Wilma"};
var a   = [42, 27];
foo.apply(obj, a); // alerts "Wilma", "42", and "27"
//             ^-- Note this is one argument, an array of arguments for `foo`

然而,在JavaScript中,关于this还有很多需要探索的内容。这个概念非常强大,如果你习惯了其他一些语言的方式,可能会有点误导(但对于其他一些语言则不是)。了解这个概念非常值得。

下面是一些在ES5严格模式下this不指向对象的例子:

(function() {
    "use strict";   // Strict mode

    test("direct");
    test.call(5, "with 5");
    test.call(true, "with true");
    test.call("hi", "with 'hi'");

    function test(msg) {
        console.log("[Strict] " + msg + "; typeof this = " + typeof this);
    }
})();

输出:

[Strict] 直接; typeof this = undefined
[Strict] with 5; typeof this = number
[Strict] with true; typeof this = boolean
[Strict] with 'hi'; typeof this = string

而在松散模式下,所有这些都会说typeof this = object; live copy


这里是我简单的解释:this指的是调用函数的对象。由于differentObj调用了foo(),所以this将指向differentObj。因为f在全局范围内定义,所以它是window对象的一个方法,因此this指向window。由于window对象没有firstName属性,所以this.firstName返回undefined。有趣的事实:在全局范围内定义的任何东西(即顶层/级别)都成为window对象的一个属性(全局范围= window对象)。 - ryanwaite28
2
@ryanwaite28:"this 指的是调用函数的对象"。不是的。对象不会调用方法,代码才会;在JavaScript中,代码与对象之间仅有松散的联系。当代码调用方法时,它会明确或隐式地将this的值设置为任意值 - 在严格模式下,它甚至可能不是一个对象引用,而是一个原始值。 - T.J. Crowder
Crowder 技术上是对的。但为了以一种人们可以理解的方式来解释它,我说了对象。但感谢您添加抽象细节。“this” 可以真正指代任何东西。 - ryanwaite28
@T.J.Crowder 我可以编辑代码片段并将它们放入堆栈片段中吗? - brk
@brk:你的意思是想编辑答案,将代码块转换为可运行的片段吗?如果是这样的话:请去做,并且谢谢! - T.J. Crowder
@T.J.Crowder 是的,我的意思就是这个。 - brk

6

this关键字

在JavaScript中,称为this的东西是“拥有”JavaScript代码的对象。

当在函数中使用时,this的值是“拥有”该函数的对象。当在对象中使用时,this的值是对象本身。 在对象构造函数中,this关键字没有值。它只是新对象的替代品。当使用构造函数创建一个对象时,this的值将变成新对象。

请注意,this不是一个变量。它是一个关键字。您无法改变this的值。


4

以下是我简单的解释:

this 指的是调用 functionobject

因此,看这个例子:

var foo = {
  name: "foo",
  log: function(){
    console.log(this.name);
  }
}

var bar = {
  name: "bar"
}
bar.log = foo.log;
bar.log();

bar对象将foo的log方法引用存储到自己的log属性中,供自己使用。现在当bar调用其log方法时,this将指向bar,因为该方法是由bar对象调用的。

这适用于任何其他对象,甚至是window对象。如果通过全局作用域调用函数,则this将指向window对象。

通过使用函数的bind或call方法,可以显式地定义执行期间对象this将引用哪个对象。

有趣的事实:在全局作用域(即顶层/级别)中定义的任何内容都成为window对象的属性(全局作用域= window对象)。


1

“javascript this” 的谷歌搜索结果前一位:http://www.quirksmode.org/js/this.html

编辑:我认为关键句子是:

“在 JavaScript 中,“this” 总是指正在执行的函数的“所有者”,或者更确切地说,是该函数作为方法的对象。”

Quirksmode(通常*)非常出色,值得详细阅读整篇文章。

*显然,这种说法不一定正确,请参见 T.J. Crowder 的下面评论。


不是用JavaScript,而是用jQuery实现的。无论如何还是谢谢! :D - JCm
5
jQuery 用Javascript编写的。任何jQuery代码也都是Javascript。 - Gareth
“在JavaScript中,“this”始终指的是我们正在执行的函数的“所有者”,或者更确切地说,是该函数作为方法所属的对象。”哇,我希望这篇文章的其余部分比这句话好。这句话延续了一个破坏性的神话,不符合quirksmode通常的标准。 - T.J. Crowder
@T.J.Crowder,您能解释一下这个神话或者提供更多关于您所说的内容的信息链接吗? - Daniel Sokolowski
@DanielSokolowski:我的博客上有两篇文章:神话般的方法你必须记住this。 :-) - T.J. Crowder

0
关键字 this 充当一个占位符,当在 JavaScript 中实际使用该方法时,它将引用调用该方法的任何对象。

-1

常规函数属于定义这些函数的类,调用函数的同一对象作为第一个参数传递给函数,并使用this关键字处理它;

当从类创建对象时,它仅包含一组属性,而对象中没有函数。函数属于类。 但是,如何通过对象调用函数呢?

请考虑以下代码。

var obj = {
            p1: 'property 1',

            func1 () {
                return this.p1
            },

            func2 (param) {
                return this.p1 + param
            }
    }

同时也可以通过obj对象调用函数

obj.func1 ();
obj.func2 ('A');

实际上,在运行时,函数看起来像以下内容。
var obj = {
            p1: 'property 1',

            func1 (this) {
                return this.p1
            },

            func2 (this, param) {
                return this.p1 + param
            }
    }

func1 (obj);
func2 (obj, 'A');

使用 bind 方法可以创建一个新函数,该函数不属于类,并可以将 'this' 参数设置为固定对象;

this.func1 = this.func1.bind(aObject)

在箭头函数中,this 绑定到定义箭头函数的对象,并将该对象作为 this 参数传递给函数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接