“this”关键字如何运作?

时间:2010-06-27 13:12:56

标签: javascript this

我注意到,似乎没有明确说明this关键字是什么以及如何在Stack Overflow站点上的JavaScript中正确(和错误地)使用它。

我目睹了一些非常奇怪的行为,并且无法理解为什么会发生这种行为。

this如何运作以及何时使用?

24 个答案:

答案 0 :(得分:1254)

答案 1 :(得分:138)

与其他语言相比,this关键字在JavaScript中的行为有所不同。在面向对象语言中,this关键字引用类的当前实例。在JavaScript中,this的值主要取决于函数的调用上下文( context.function() )以及调用它的位置。

<强> 1。在全球范围内使用时

在全局上下文中使用this时,它绑定到全局对象(浏览器中为window

document.write(this);  //[object Window]

当在全局上下文中定义的函数中使用this时,this仍然绑定到全局对象,因为该函数实际上是一个全局上下文的方法。

function f1()
{
   return this;
}
document.write(f1());  //[object Window]

以上f1是一个全局对象的方法。因此,我们也可以在window对象上调用它,如下所示:

function f()
{
    return this;
}

document.write(window.f()); //[object Window]

<强> 2。在对象方法中使用时

在对象方法中使用this关键字时,this绑定到&#34;立即&#34;封闭对象。

var obj = {
    name: "obj",
    f: function () {
        return this + ":" + this.name;
    }
};
document.write(obj.f());  //[object Object]:obj

上面我已将单词立即用双引号括起来。重点是,如果将对象嵌套在另一个对象中,则this绑定到直接父对象。

var obj = {
    name: "obj1",
    nestedobj: {
        name:"nestedobj",
        f: function () {
            return this + ":" + this.name;
        }
    }            
}

document.write(obj.nestedobj.f()); //[object Object]:nestedobj

即使您将函数显式添加到对象作为方法,它仍然遵循上述规则,即this仍然指向直接父对象。

var obj1 = {
    name: "obj1",
}

function returnName() {
    return this + ":" + this.name;
}

obj1.f = returnName; //add method to object
document.write(obj1.f()); //[object Object]:obj1

第3。调用无上下文函数时

当你在没有任何上下文的情况下使用this内部函数(即不在任何对象上)时,它被绑定到全局对象(浏览器中的window)(即使定义了函数)在对象内部。)

var context = "global";

var obj = {  
    context: "object",
    method: function () {                  
        function f() {
            var context = "function";
            return this + ":" +this.context; 
        };
        return f(); //invoked without context
    }
};

document.write(obj.method()); //[object Window]:global 

使用功能尝试所有功能

我们也可以尝试以上功能。然而,存在一些差异。

  • 上面我们使用对象文字表示法向对象添加了成员​​。我们可以使用this向函数添加成员。指定它们。
  • 对象文字表示法创建一个我们可以立即使用的对象实例。使用函数,我们可能需要首先使用new运算符创建其实例。
  • 同样在对象文字方法中,我们可以使用点运算符显式地将成员添加到已定义的对象。这仅添加到特定实例。但是我已经在函数原型中添加了变量,以便它反映在函数的所有实例中。

下面我尝试了上面用Object和this做的所有事情,但首先是创建函数而不是直接编写对象。

/********************************************************************* 
  1. When you add variable to the function using this keyword, it 
     gets added to the function prototype, thus allowing all function 
     instances to have their own copy of the variables added.
*********************************************************************/
function functionDef()
{
    this.name = "ObjDefinition";
    this.getName = function(){                
        return this+":"+this.name;
    }
}        

obj1 = new functionDef();
document.write(obj1.getName() + "<br />"); //[object Object]:ObjDefinition   

/********************************************************************* 
   2. Members explicitly added to the function protorype also behave 
      as above: all function instances have their own copy of the 
      variable added.
*********************************************************************/
functionDef.prototype.version = 1;
functionDef.prototype.getVersion = function(){
    return "v"+this.version; //see how this.version refers to the
                             //version variable added through 
                             //prototype
}
document.write(obj1.getVersion() + "<br />"); //v1

/********************************************************************* 
   3. Illustrating that the function variables added by both above 
      ways have their own copies across function instances
*********************************************************************/
functionDef.prototype.incrementVersion = function(){
    this.version = this.version + 1;
}
var obj2 = new functionDef();
document.write(obj2.getVersion() + "<br />"); //v1

obj2.incrementVersion();      //incrementing version in obj2
                              //does not affect obj1 version

document.write(obj2.getVersion() + "<br />"); //v2
document.write(obj1.getVersion() + "<br />"); //v1

/********************************************************************* 
   4. `this` keyword refers to the immediate parent object. If you 
       nest the object through function prototype, then `this` inside 
       object refers to the nested object not the function instance
*********************************************************************/
functionDef.prototype.nestedObj = { name: 'nestedObj', 
                                    getName1 : function(){
                                        return this+":"+this.name;
                                    }                            
                                  };

document.write(obj2.nestedObj.getName1() + "<br />"); //[object Object]:nestedObj

/********************************************************************* 
   5. If the method is on an object's prototype chain, `this` refers 
      to the object the method was called on, as if the method was on 
      the object.
*********************************************************************/
var ProtoObj = { fun: function () { return this.a } };
var obj3 = Object.create(ProtoObj); //creating an object setting ProtoObj
                                    //as its prototype
obj3.a = 999;                       //adding instance member to obj3
document.write(obj3.fun()+"<br />");//999
                                    //calling obj3.fun() makes 
                                    //ProtoObj.fun() to access obj3.a as 
                                    //if fun() is defined on obj3

<强> 4。在构造函数内部使用时。

当函数用作构造函数时(即使用new关键字调用它时),函数体内的this指向正在构造的新对象。

var myname = "global context";
function SimpleFun()
{
    this.myname = "simple function";
}

var obj1 = new SimpleFun(); //adds myname to obj1
//1. `new` causes `this` inside the SimpleFun() to point to the
//   object being constructed thus adding any member
//   created inside SimipleFun() using this.membername to the
//   object being constructed
//2. And by default `new` makes function to return newly 
//   constructed object if no explicit return value is specified

document.write(obj1.myname); //simple function

<强> 5。在原型链中定义的函数内部使用时

如果方法在对象的原型链上,则此方法中的this引用调用该方法的对象,就像在对象上定义了该方法一样。

var ProtoObj = {
    fun: function () {
        return this.a;
    }
};
//Object.create() creates object with ProtoObj as its
//prototype and assigns it to obj3, thus making fun() 
//to be the method on its prototype chain

var obj3 = Object.create(ProtoObj);
obj3.a = 999;
document.write(obj3.fun()); //999

//Notice that fun() is defined on obj3's prototype but 
//`this.a` inside fun() retrieves obj3.a   

<强> 6。内部call(),apply()和bind()函数

  • 所有这些方法都在Function.prototype上定义。
  • 这些方法允许编写一次函数并在不同的上下文中调用它。换句话说,它们允许指定在执行函数时将使用的this的值。它们还会在调用时将任何参数传递给原始函数。
  • fun.apply(obj1 [, argsArray]) obj1设置为thisfun()的值,并调用fun()传递argsArray的元素}作为其论点。
  • fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]]) - 将obj1设置为thisfun()的值,并通过fun()调用arg1, arg2, arg3, ...作为其论点。
  • fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]]) - 返回对fun函数的引用,其中this位于obj1fun的参数范围内绑定到指定的参数arg1, arg2, arg3,...
  • 到目前为止,applycallbind之间的区别必须明显。 apply允许指定用作类数组对象的参数,即具有数字length属性的对象和相应的非负整数属性。而call允许直接指定函数的参数。 applycall都会立即调用指定上下文中的函数并使用指定的参数。另一方面,bind只返回绑定到指定this值和参数的函数。我们可以通过将其分配给变量来捕获对此返回函数的引用,之后我们可以随时调用它。
function add(inc1, inc2)
{
    return this.a + inc1 + inc2;
}

var o = { a : 4 };
document.write(add.call(o, 5, 6)+"<br />"); //15
      //above add.call(o,5,6) sets `this` inside
      //add() to `o` and calls add() resulting:
      // this.a + inc1 + inc2 = 
      // `o.a` i.e. 4 + 5 + 6 = 15
document.write(add.apply(o, [5, 6]) + "<br />"); //15
      // `o.a` i.e. 4 + 5 + 6 = 15

var g = add.bind(o, 5, 6);       //g: `o.a` i.e. 4 + 5 + 6
document.write(g()+"<br />");    //15

var h = add.bind(o, 5);          //h: `o.a` i.e. 4 + 5 + ?
document.write(h(6) + "<br />"); //15
      // 4 + 5 + 6 = 15
document.write(h() + "<br />");  //NaN
      //no parameter is passed to h()
      //thus inc2 inside add() is `undefined`
      //4 + 5 + undefined = NaN</code>

<强> 7。事件处理程序中的this

  • 当您将函数直接赋值给元素的事件处理程序时,在事件处理函数内直接使用this指的是相应的元素。这种直接函数分配可以使用addeventListener方法或通过onclick等传统事件注册方法完成。
  • 同样,当您在元素的事件属性(如this)内直接使用<button onclick="...this..." >时,它会引用该元素。
  • 但是,通过事件处理函数或事件属性内部调用的其他函数间接使用this会解析为全局对象window
  • 当我们使用Microsoft的事件注册模型方法attachEvent将函数附加到事件处理程序时,可以实现相同的上述行为。它不是将函数赋值给事件处理程序(从而构成元素的函数方法),而是调用事件上的函数(在全局上下文中有效地调用它)。

我建议您最好在JSFiddle中尝试此操作。

<script> 
    function clickedMe() {
       alert(this + " : " + this.tagName + " : " + this.id);
    } 
    document.getElementById("button1").addEventListener("click", clickedMe, false);
    document.getElementById("button2").onclick = clickedMe;
    document.getElementById("button5").attachEvent('onclick', clickedMe);   
</script>

<h3>Using `this` "directly" inside event handler or event property</h3>
<button id="button1">click() "assigned" using addEventListner() </button><br />
<button id="button2">click() "assigned" using click() </button><br />
<button id="button3" onclick="alert(this+ ' : ' + this.tagName + ' : ' + this.id);">used `this` directly in click event property</button>

<h3>Using `this` "indirectly" inside event handler or event property</h3>
<button onclick="alert((function(){return this + ' : ' + this.tagName + ' : ' + this.id;})());">`this` used indirectly, inside function <br /> defined & called inside event property</button><br />

<button id="button4" onclick="clickedMe()">`this` used indirectly, inside function <br /> called inside event property</button> <br />

IE only: <button id="button5">click() "attached" using attachEvent() </button>

答案 2 :(得分:54)

Javascript&#39; s this

简单函数调用

考虑以下功能:

function foo() {
    console.log("bar");
    console.log(this);
}
foo(); // calling the function

请注意,我们在正常模式下运行它,即不使用严格模式。

在浏览器中运行时,this的值将记录为window。这是因为window是Web浏览器范围内的全局变量。

如果您在node.js这样的环境中运行同一段代码,this会引用您应用中的全局变量。

现在,如果我们在严格模式下通过将语句"use strict";添加到函数声明的开头来运行它,this将不再引用任何环境中的全局变量。这样做是为了避免严格模式下的混淆。在这种情况下,this只会记录undefined,因为它就是这样,它没有被定义。

在以下情况中,我们将看到如何操纵this

的值

在对象上调用函数

有不同的方法可以做到这一点。如果您在forEachslice等Javascript中调用了本机方法,那么您应该已经知道this变量在这种情况下引用了您调用该函数的Object (请注意,在javascript中,几乎所有内容都是Object,包括ArrayFunction s。以下面的代码为例。

var myObj = {key: "Obj"};
myObj.logThis = function () {
    // I am a method
    console.log(this);
}
myObj.logThis(); // myObj is logged

如果Object包含一个包含Function的属性,则该属性称为方法。调用此方法时,将始终将this变量设置为与其关联的Object。对于严格和非严格模式都是如此。

请注意,如果方法存储(或者更确切地说,复制)在另一个变量中,则对this的引用不再保留在新变量中。例如:

// continuing with the previous code snippet

var myVar = myObj.thisMethod;
myVar();
// logs either of window/global/undefined based on mode of operation

考虑更常见的实际情况:

var el = document.getElementById('idOfEl');
el.addEventListener('click', function() { console.log(this) });
// the function called by addEventListener contains this as the reference to the element
// so clicking on our element would log that element itself

new关键字

考虑Javascript中的构造函数:

function Person (name) {
    this.name = name;
    this.sayHello = function () {
        console.log ("Hello", this);
    }
}

var awal = new Person("Awal");
awal.sayHello();
// In `awal.sayHello`, `this` contains the reference to the variable `awal`

这是如何工作的?好吧,让我们看看当我们使用new关键字时会发生什么。

  1. 使用new关键字调用该函数会立即初始化Object类型Person
  2. Object的构造函数的构造函数设置为Person。另请注意,typeof awal仅返回Object
  3. 这个新的Object将被分配Person.prototype的原型。这意味着Person原型中的任何方法或属性都可用于Person的所有实例,包括awal
  4. 现在调用函数Person本身; this是对新构造的对象awal的引用。
  5. 非常简单,嗯?

    请注意,官方的ECMAScript规范没有说明这类函数是实际的constructor函数。它们只是普通函数,new可用于任何函数。只是我们这样使用它们,因此我们只将它们称为它们。

    在函数上调用函数:callapply

    所以是的,既然function也是Objects(实际上是Javascript中的第一类变量),甚至函数都有......好吧,函数本身。

    所有功能都从全局Function继承,其中有两种方法是callapply,两者都可用于操纵this的值它们被称为的函数。

    function foo () { console.log (this, arguments); }
    var thisArg = {myObj: "is cool"};
    foo.call(thisArg, 1, 2, 3);
    

    这是使用call的典型示例。它基本上采用第一个参数,并在函数this中设置foo作为对thisArg的引用。传递给call的所有其他参数作为参数传递给函数foo 因此,上面的代码将在控制台中记录{myObj: "is cool"}, [1, 2, 3]。在任何函数中更改this的值的非常好的方法。

    applycall几乎相同,只接受两个参数:thisArg和一个包含要传递给函数的参数的数组。因此,上述call调用可以像这样翻译为apply

    foo.apply(thisArg, [1,2,3])
    

    请注意,callapply可以覆盖我们在第二个项目符号中讨论的点方法调用设置的this的值。 很简单:)

    呈现.... bind

    bindcallapply的兄弟。它也是Javascript中全局Function构造函数的所有函数继承的方法。 bindcall / apply之间的区别在于callapply实际上都会调用该函数。另一方面,bind会返回一个预设thisArgarguments的新函数。让我们举一个例子来更好地理解这一点:

    function foo (a, b) {
        console.log (this, arguments);
    }
    var thisArg = {myObj: "even more cool now"};
    var bound = foo.bind(thisArg, 1, 2);
    console.log (typeof bound); // logs `function`
    console.log (bound);
    /* logs `function () { native code }` */
    
    bound(); // calling the function returned by `.bind`
    // logs `{myObj: "even more cool now"}, [1, 2]`
    

    看到三者之间的区别?它很微妙,但它们的使用方式不同。与callapply一样,bind也会覆盖由点方法调用设置的this值。

    另请注意,这三个功能都不会对原始功能进行任何更改。 callapply将从新构造的函数返回值,而bind将返回新构造的函数本身,随时可以调用。

    额外的东西,复制这个

    有时,您不喜欢this随范围变化的事实,尤其是嵌套范围。看一下下面的例子。

    var myObj = {
        hello: function () {
            return "world"
            },
        myMethod: function () {
            // copy this, variable names are case-sensitive
            var that = this;
            // callbacks ftw \o/
            foo.bar("args", function () {
                // I want to call `hello` here
                this.hello(); // error
                // but `this` references to `foo` damn!
                // oh wait we have a backup \o/
                that.hello(); // "world"
            });
        }
      };
    

    在上面的代码中,我们看到this的值随嵌套范围而变化,但我们希望原始范围内的this值。所以我们复制了#39; thisthat并使用了副本而不是this。聪明,嗯?

    指数:

    1. 默认情况下this中的内容是什么?
    2. 如果我们将该函数称为具有Object-dot表示法的方法怎么办?
    3. 如果我们使用new关键字
    4. ,该怎么办?
    5. 我们如何使用thiscall操纵apply
    6. 使用bind
    7. 复制this以解决嵌套范围问题。

答案 3 :(得分:46)

“这个”就是范围。每个函数都有自己的作用域,因为JS中的所有东西都是一个对象,所以即使函数也可以使用“this”将一些值存储到自身中。 OOP 101教导“this”仅适用于对象的实例。因此,每次执行一个函数时,该函数的新“实例”都具有“this”的新含义。

大多数人在尝试在匿名闭包函数中使用“this”时会感到困惑:

(function(value) {
    this.value = value;
    $('.some-elements').each(function(elt){
        elt.innerHTML = this.value;        // uh oh!! possibly undefined
    });
})(2);

所以在这里,在每个()中,“this”不包含你期望它的“值”(从它上面的

this.value = value;
)。因此,为了克服这个问题(没有双关语)问题,开发人员可以:

(function(value) {
    var self = this;            // small change
    self.value = value;
    $('.some-elements').each(function(elt){
        elt.innerHTML = self.value;        // phew!! == 2 
    });
})(2);

尝试一下;你会开始喜欢这种编程模式

答案 4 :(得分:16)

由于这个帖子已经出现问题,我已经为刚接触this主题的读者编了几点。

this的值是如何确定的?

我们使用类似于我们在英语等自然语言中使用代词的方式:“约翰跑得快,因为 正试图赶上火车。”相反,我们本来可以写“...... John 正试图赶上火车”。

var person = {    
    firstName: "Penelope",
    lastName: "Barrymore",
    fullName: function () {

    // We use "this" just as in the sentence above:
       console.log(this.firstName + " " + this.lastName);

    // We could have also written:
       console.log(person.firstName + " " + person.lastName);
    }
}
在对象调用定义它的函数之前,

this 未分配值。在全局范围内,所有全局变量和函数都在window对象上定义。因此,全局函数中的this引用全局window对象(并具有其值)。

use strict时,未绑定到任何对象的全局和匿名函数中的this值为undefined

this关键字为most misunderstood时:1)我们借用了使用this的方法,2)我们为变量分配了一个使用this的方法,3 )使用this的函数作为回调函数传递,4)this在闭包内部使用 - 内部函数。 (2)

table

未来是什么

ECMA Script 6中定义,箭头函数采用来自的this绑定 封闭(功能或全局)范围。

function foo() {
     // return an arrow function
     return (a) => {
     // `this` here is lexically inherited from `foo()`
     console.log(this.a);
  };
}
var obj1 = { a: 2 };
var obj2 = { a: 3 };

var bar = foo.call(obj1);
bar.call( obj2 ); // 2, not 3!

虽然箭头函数提供了使用bind()的替代方法,但重要的是要注意它们基本上禁用传统的this机制,以支持更广泛理解的词法范围。 (1)


<强> 参考文献:

  1. 此&amp;对象原型,作者:Kyle Simpson。 ©2014 Getify Solutions。
  2. javascriptissexy.com - http://goo.gl/pvl0GX
  3. Angus Croll - http://goo.gl/Z2RacU

答案 5 :(得分:16)

Javascript中的

this始终指的是正在执行的函数的“所有者”。

如果未定义显式所有者,则引用最顶层的所有者即窗口对象。

所以,如果我做了

function someKindOfFunction() {
   this.style = 'foo';
}

element.onclick = someKindOfFunction;

this将引用元素对象。但要小心,很多人犯了这个错误

<element onclick="someKindOfFunction()">

在后一种情况下,您只需引用该函数,而不是将其移交给元素。因此,this将引用窗口对象。

答案 6 :(得分:12)

javascript中的每个函数 执行上下文都有范围 上下文 参数由以下人员设定:

  1. 如何调用该函数(包括作为对象方法,使用调用应用,使用 new
  2. 使用 bind
  3. 用于箭头函数的词法(他们采用外部执行上下文的 this
  4. 无论范围上下文是什么,都以“this”引用。

    您可以使用func.call更改设置 范围 context 的值,{ {1}}或func.apply

    默认情况下,大多数初学者都会感到困惑,当在DOM元素上引发事件后调用回调侦听器时,范围上下文 this < / em>函数的值是DOM元素。

    jQuery使用jQuery.proxy来改变这一点。

答案 7 :(得分:10)

HerethisJavaScript的一个很好的来源。

以下是摘要:

  • 全球

    在浏览器中,在全局范围内,thiswindow对象

    <script type="text/javascript">
      console.log(this === window); // true
      var foo = "bar";
      console.log(this.foo); // "bar"
      console.log(window.foo); // "bar"
    

    在使用repl的node中,this是顶级命名空间。您可以将其称为global

    >this
      { ArrayBuffer: [Function: ArrayBuffer],
        Int8Array: { [Function: Int8Array] BYTES_PER_ELEMENT: 1 },
        Uint8Array: { [Function: Uint8Array] BYTES_PER_ELEMENT: 1 },
        ...
    >global === this
     true
    

    node执行脚本时,全局范围内的this作为空对象开始。它与global

    不同
    \\test.js
    console.log(this);  \\ {}
    console.log(this === global); \\ fasle
    
  • 此功能

除了DOM事件处理程序或提供thisArg时(参见下文),在节点和浏览器中使用this的函数都未使用{{ 1}}引用全局范围......

new

如果您使用<script type="text/javascript"> foo = "bar"; function testThis() { this.foo = "foo"; } console.log(this.foo); //logs "bar" testThis(); console.log(this.foo); //logs "foo" </script> ,则use strict;this

undefined

如果您使用<script type="text/javascript"> foo = "bar"; function testThis() { "use strict"; this.foo = "foo"; } console.log(this.foo); //logs "bar" testThis(); //Uncaught TypeError: Cannot set property 'foo' of undefined </script> 调用某个函数,则new将成为新的上下文,它将不会引用全局this

this
  • 原型

您创建的函数将成为函数对象。它们会自动获得一个特殊的<script type="text/javascript"> foo = "bar"; function testThis() { this.foo = "foo"; } console.log(this.foo); //logs "bar" new testThis(); console.log(this.foo); //logs "bar" console.log(new testThis().foo); //logs "foo" </script> 属性,您可以为其赋值。通过使用prototype调用函数创建实例时,您可以访问分配给new属性的值。您可以使用prototype访问这些值。

this

function Thing() { console.log(this.foo); } Thing.prototype.foo = "bar"; var thing = new Thing(); //logs "bar" console.log(thing.foo); //logs "bar" 上分配数组对象通常是错误的。如果您希望每个实例都有自己的数组,请在函数中创建它们,而不是原型。

prototype
  • 反对此

您可以在对象的任何函数中使用function Thing() { this.things = []; } var thing1 = new Thing(); var thing2 = new Thing(); thing1.things.push("foo"); console.log(thing1.things); //logs ["foo"] console.log(thing2.things); //logs [] 来引用该对象上的其他属性。这与使用this创建的实例不同。

new
  • DOM事件

在HTML DOM事件处理程序中,var obj = { foo: "bar", logFoo: function () { console.log(this.foo); } }; obj.logFoo(); //logs "bar" 始终是对事件附加到的DOM元素的引用

this

除非你function Listener() { document.getElementById("foo").addEventListener("click", this.handleClick); } Listener.prototype.handleClick = function (event) { console.log(this); //logs "<div id="foo"></div>" } var listener = new Listener(); document.getElementById("foo").click(); 上下文

bind
  • HTML

在您可以放置​​JavaScript的HTML内部属性中,function Listener() { document.getElementById("foo").addEventListener("click", this.handleClick.bind(this)); } Listener.prototype.handleClick = function (event) { console.log(this); //logs Listener {handleClick: function} } var listener = new Listener(); document.getElementById("foo").click(); 是对元素的引用。

this
  • 评估

您可以使用<div id="foo" onclick="console.log(this);"></div> <script type="text/javascript"> document.getElementById("foo").click(); //logs <div id="foo"... </script> 访问eval

this
  • 使用此

您可以使用function Thing () { } Thing.prototype.foo = "bar"; Thing.prototype.logFoo = function () { eval("console.log(this.foo)"); //logs "bar" } var thing = new Thing(); thing.logFoo(); with添加到当前范围,以便在this上读取和写入值,而无需明确引用this

this
  • jQuery this

jQuery将在很多地方function Thing () { } Thing.prototype.foo = "bar"; Thing.prototype.logFoo = function () { with (this) { console.log(foo); foo = "foo"; } } var thing = new Thing(); thing.logFoo(); // logs "bar" console.log(thing.foo); // logs "foo" 引用DOM元素。

this

答案 8 :(得分:9)

丹尼尔,很棒的解释!在事件处理程序的情况下,这个和this执行上下文指针的良好列表上的几个单词。

用两个词来说,JavaScript中的this指向运行当前函数的对象(或从其执行上下文),并且它始终是只读的,无论如何都无法设置它(这样的尝试将会以“分配中无效的左侧”消息结束。

对于事件处理程序:内联事件处理程序(例如<element onclick="foo">)会覆盖之前和之前附加的任何其他处理程序,因此请务必小心,最好不要使用内联事件委派。 感谢Zara Alaverdyan,他通过不同的辩论激发了我对这个例子的启发:)

  • el.onclick = foo; // in the foo - obj
  • el.onclick = function () {this.style.color = '#fff';} // obj
  • el.onclick = function() {doSomething();} // In the doSomething - Window
  • el.addEventListener('click',foo,false) // in the foo - obj
  • el.attachEvent('onclick, function () { // this }') // window, all the compliance to IE :)
  • <button onclick="this.style.color = '#fff';"> // obj
  • <button onclick="foo"> // In the foo - window, but you can <button onclick="foo(this)">

答案 9 :(得分:9)

关于this的最详细和最全面的文章可能如下:

Gentle explanation of 'this' keyword in JavaScript

this背后的想法是要理解函数调用类型对设置this值具有重要意义。

如果遇到问题this问自己:

  

this取自

问自己:

  

如何调用函数

对于箭头功能(上下文透明度的特殊情况),请问自己:

  

箭头函数定义的哪个值为this

在处理this时,这种心态是正确的,并且可以免除头痛。

答案 10 :(得分:9)

关于如何在JavaScript中解释&#34;此&#34; 关键字存在很多混淆。希望这篇文章能够让所有人一劳永逸地休息。还有更多。请仔细阅读整篇文章。预先警告这篇文章很长。

无论使用它的上下文如何,&#34;此&#34; 始终引用Javascript中的&#34;当前对象&#34; 。但是,&#34;当前对象&#34; 根据上下文而有所不同。 上下文可能正好是以下中的中的一个

  1. 全球(即所有功能之外)
  2. 内部直接&#34;非约束功能&#34;通过调用 functionName.bind 来调用(即约束的功能)
  3. 内部间接&#34;非约束功能&#34;通过 functionName.call functionName.apply
  4. 致电
  5. 内部&#34;绑定功能&#34;通过调用 functionName.bind 来调用(即已绑定的功能)
  6. 通过&#34; new&#34;
  7. 创建对象时
  8. 内联DOM事件处理程序
  9. 以下逐一描述每个上下文:

    1. 全球背景(即所有功能之外):

      在所有功能之外(即在全局范围内)&#34;当前 对象&#34; (因此&#34;这个&#34; 的值)始终是 浏览器的&#34;窗口&#34; 对象。

    2. 内部直接&#34;非约束功能&#34;致电

      直接&#34;非约束功能&#34;打电话,那个对象 调用函数调用成为&#34;当前对象&#34; (因此 &#34;此&#34; )的值。如果在没有明确当前对象的情况下调用函数,则当前对象&#34;窗口&#34; 对象(对于非严格模式)或未定义(适用于严格模式)。中定义的任何函数(或变量) 全局上下文会自动成为&#34;窗口&#34; 对象的属性。例如假设函数在全局上下文中定义为

      function UserDefinedFunction(){
          alert(this)
          }
      

      它成为窗口对象的属性,就像你已经定义了一样 它是

      window.UserDefinedFunction=function(){
        alert(this)
      }  
      

      在&#34;非严格模式&#34;,直接通过&#34; UserDefinedFunction()&#34; 调用/调用此功能将自动调用/调用 它作为&#34; window.UserDefinedFunction()&#34; 使&#34;窗口&#34; 作为 &#34;当前对象&#34; (以及&#34;此&#34; 的值)&#34; UserDefinedFunction&#34; 。在&#34;非严格模式&#34;中调用此功能将导致以下

      UserDefinedFunction() // displays [object Window]  as it automatically gets invoked as window.UserDefinedFunction()
      

      在&#34;严格模式&#34;,直接通过调用/调用函数 &#34; UserDefinedFunction()&#34; &#34; NOT&#34; 自动调用/调用它作为&#34; window.UserDefinedFunction ()&#34; &#34;当前 对象&#34; (以及&#34;此&#34; 的值) &#34; UserDefinedFunction&#34; 未定义。在&#34;严格模式&#34;中调用此功能将导致以下

      UserDefinedFunction() // displays undefined
      

      但是,使用window对象显式调用它会导致 以下

      window.UserDefinedFunction() // "always displays [object Window]   irrespective of mode."
      

      让我们看看另一个例子。请查看以下代码

       function UserDefinedFunction()
          {
              alert(this.a + ","  + this.b + ","  + this.c  + ","  + this.d)
          }
      
      var o1={
                  a:1,
                  b:2,
                  f:UserDefinedFunction
            }
      var o2={
                  c:3,
                  d:4,
                  f:UserDefinedFunction
             }
      
      o1.f() // Shall display 1,2,undefined,undefined
      o2.f() // Shall display undefined,undefined,3,4
      

      在上面的示例中,我们看到&#34; UserDefinedFunction&#34; 是 通过 o1 &#34进行调用;此&#34; 取值 o1 和 其属性值&#34; a&#34; &#34; b&#34; 会显示。价值 &#34; c&#34; &#34; d&#34; 显示为未定义 o1 做 没有定义这些属性

      同样,当&#34; UserDefinedFunction&#34; 通过 o2 调用时, &#34;此&#34; 取值 o2 及其属性值&#34; c&#34; &#34; d&#34; 显示。&#34; a&#34; &#34; b&#34; 的值显示为未定义,因为 o2 未定义这些属性。

    3. 内部间接&#34;非约束功能&#34;通过 functionName.call functionName.apply 致电

      当调用&#34;非约束函数&#34; functionName.call functionName.apply &#34;当前对象&#34; < / strong>(因此&#34;此&#34; 的值)设置为值 &#34;此&#34; 参数(第一个参数)传递给调用/应用。以下代码演示了相同的内容。

      function UserDefinedFunction()
      {
          alert(this.a + ","  + this.b + ","  + this.c  + ","  + this.d)
      }
      var o1={
                  a:1,
                  b:2,
                  f:UserDefinedFunction
             }
      var o2={
                  c:3,
                  d:4,
                  f:UserDefinedFunction
             }
      
      UserDefinedFunction.call(o1) // Shall display 1,2,undefined,undefined
      UserDefinedFunction.apply(o1) // Shall display 1,2,undefined,undefined
      
      UserDefinedFunction.call(o2) // Shall display undefined,undefined,3,4
      UserDefinedFunction.apply(o2) // Shall display undefined,undefined,3,4
      
      o1.f.call(o2) // Shall display undefined,undefined,3,4
      o1.f.apply(o2) // Shall display undefined,undefined,3,4
      
      o2.f.call(o1) // Shall display 1,2,undefined,undefined
      o2.f.apply(o1) // Shall display 1,2,undefined,undefined
      

      上面的代码清楚地表明了这个&#34;这个&#34;任何&#34; NON的价值 绑定功能&#34;可以通过呼叫/应用进行更改。另外,如果 &#34;此&#34; 参数未明确传递给调用/应用&#34;当前对象&#34; (和因此&#34;此&#34;)的值在非严格模式下设置为&#34; window&#34; &#34; undefined&#34; 严格模式。

    4. 内部&#34;绑定功能&#34;调用(即通过调用 functionName.bind 绑定的函数):

      绑定函数是&#34;此&#34; 值的函数 固定。以下代码演示了&#34;此&#34; 的工作原理 绑定函数

      function UserDefinedFunction()
      {
          alert(this.a + ","  + this.b + ","  + this.c  + ","  + this.d)
      }
      var o1={
                a:1,
                b:2,
                f:UserDefinedFunction,
                bf:null
             }
      var o2={
                 c:3,
                 d:4,
                 f:UserDefinedFunction,
                 bf:null
              }
      
      var bound1=UserDefinedFunction.bind(o1); // permanantly fixes "this" value of function "bound1" to Object o1
      bound1() // Shall display 1,2,undefined,undefined
      
      var bound2=UserDefinedFunction.bind(o2); // permanantly fixes "this" value of function "bound2" to Object o2
      bound2() // Shall display undefined,undefined,3,4
      
      var bound3=o1.f.bind(o2); // permanantly fixes "this" value of function "bound3" to Object o2
      bound3() // Shall display undefined,undefined,3,4
      
      var bound4=o2.f.bind(o1); // permanantly fixes "this" value of function "bound4" to Object o1
      bound4() // Shall display 1,2,undefined,undefined
      
      o1.bf=UserDefinedFunction.bind(o2) // permanantly fixes "this" value of function "o1.bf" to Object o2
      o1.bf() // Shall display undefined,undefined,3,4
      
      o2.bf=UserDefinedFunction.bind(o1) // permanantly fixes "this" value of function "o2.bf" to Object o1
      o2.bf() // Shall display 1,2,undefined,undefined
      
      bound1.call(o2) // Shall still display 1,2,undefined,undefined. "call" cannot alter the value of "this" for bound function
      
      bound1.apply(o2) // Shall still display 1,2,undefined,undefined. "apply" cannot alter the value of "this" for bound function
      
      o2.bf.call(o2) // Shall still display 1,2,undefined,undefined. "call" cannot alter the value of "this" for bound function
      o2.bf.apply(o2) // Shall still display 1,2,undefined,undefined."apply" cannot alter the value of "this" for bound function
      

      如上面的代码所示,&#34; this&#34;任何&#34;绑定功能&#34;的值 不能通过电话/申请进行更改。此外,如果&#34;此&#34; 参数未明确传递给bind,&#34;当前对象&#34; (因此&#34;此&#34; )的值设置为非&#34;窗口&#34; 在严格模式下严格模式和&#34; undefined&#34; 。还有一件事。 绑定已绑定的函数不会更改&#34;此&#34; 的值。 它仍然设置为第一个绑定函数设置的值。

    5. 通过&#34; new&#34; 创建对象时:

      在构造函数内部,&#34;当前对象&#34; (因此值 &#34;此&#34; )引用当前正在创建的对象 通过&#34; new&#34; ,无论函数的绑定状态如何。然而 如果构造函数是一个绑定函数,它将被调用 为绑定函数设置的预定义参数集。

    6. 内联DOM事件处理程序

      请查看以下HTML代码段

      <button onclick='this.style.color=white'>Hello World</button>
      <div style='width:100px;height:100px;' onclick='OnDivClick(event,this)'>Hello World</div>
      

      以上示例中的&#34;此&#34; 是指&#34;按钮&#34;元素和 &#34; DIV&#34;元素分别。

      在第一个示例中,按钮的字体颜色应设置为 单击时为白色。

      在第二个例子中,当点击&#34; div&#34; 元素时 使用第二个参数调用 OnDivClick 函数 引用单击的div元素。但是&#34;这个&#34; 的价值 在OnDivClick中不会引用点击的 div 元件。它应设置为&#34;窗口对象&#34; 或 分别在非严格严格模式&#34; undefined&#34; (如果 OnDivClick 未绑定功能)或设置为预定义 绑定值(如果 OnDivClick 绑定函数

    7. 以下总结了整篇文章

      1. 在全球背景下&#34;此&#34; 始终引用&#34;窗口&#34; 对象

      2. 每当调用一个函数时,都会在一个函数的上下文中调用它 对象(&#34;当前对象&#34; )。如果未明确提供当前对象当前对象 NON Strict中的&#34;窗口对象&#34; 默认情况下,模式&#34;未定义&#34; 在严格模式下。

      3. 非强制函数中&#34;此&#34; 的值是在调用函数的上下文中对象的引用(&#34;当前对象&#34;

      4. 非强制功能中&#34;此&#34; 的值可以被覆盖 调用应用函数的方法。

      5. &#34;此&#34; 的值对于Bound函数是固定的,不能是 通过调用应用函数方法覆盖。

      6. 绑定和已绑定的函数不会更改&#34;这个&#34;的值。它仍然设置为第一个绑定函数设置的值。

      7. 构造函数中&#34; this&#34; 的值是正在的对象 创建并初始化

      8. 内联DOM事件处理程序中&#34; this&#34; 的值是引用 到给出事件处理程序的元素。

答案 11 :(得分:7)

这是我见过的最好的解释。 Understand JavaScripts this with Clarity

  

this 引用始终引用(并保存)a的值   object - 一个单数对象 - 它通常用在一个函数或一个函数中   方法,虽然它可以在全局函数之外使用   范围。请注意,当我们使用严格模式时,它保持值   在全局函数和非匿名函数中未定义   绑定到任何对象。

这个有四个条件可能令人困惑:

  1. 当我们传递一个方法(使用 this )作为参数用作回调函数时。
  2. 另一个被误解的例子是我们使用内部方法(闭包)。请务必注意,闭包不能通过使用this关键字访问外部函数的 this 变量,因为此变量只能由函数本身访问,而不能由内部函数访问。
  3. 将方法分配给变量时使用 this 值绑定到另一个对象,如果我们将一个方法用于变量
  4. 使用bind,apply和call methods时使用 this
  5. 他提供了我认为非常有用的代码示例,解释和代码修复。

答案 12 :(得分:6)

如果你不完全理解JS,很难掌握JS,或者写出更多的东西。你不能只是快花钱:)我认为开始使用JS的最佳方式是首先观看Douglas Crockford撰写的这些视频讲座 - http://yuiblog.com/crockford/,其中涵盖了这个和那个,以及关于JS的所有其他内容。

答案 13 :(得分:6)

在伪古典术语中,许多讲座教授'this'关键字的方式是作为由类或对象构造函数实例化的对象。每次从一个类构造一个新对象时,想象一下,创建并返回一个'this'对象的本地实例。我记得它是这样教的:

function Car(make, model, year) {
var this = {}; // under the hood, so to speak
this.make = make;
this.model = model;
this.year = year;
return this; // under the hood
}

var mycar = new Car('Eagle', 'Talon TSi', 1993);
// ========= under the hood
var this = {};
this.make = 'Eagle';
this.model = 'Talon TSi';
this.year = 1993;
return this;

答案 14 :(得分:5)

this是JavaScript中被误解的概念之一,因为它在不同地方的行为方式略有不同。简单来说,this是指&#34;所有者&#34;我们当前正在执行的功能

this有助于获取我们使用的当前对象(a.k.a.执行上下文)。如果您了解当前函数在哪个对象中执行,您可以轻松理解当前this是什么

var val = "window.val"

var obj = {
    val: "obj.val",
    innerMethod: function () {
        var val = "obj.val.inner",
            func = function () {
                var self = this;
                return self.val;
            };

        return func;
    },
    outerMethod: function(){
        return this.val;
    }
};

//This actually gets executed inside window object 
console.log(obj.innerMethod()()); //returns window.val

//Breakdown in to 2 lines explains this in detail
var _inn = obj.innerMethod();
console.log(_inn()); //returns window.val

console.log(obj.outerMethod()); //returns obj.val

上面我们创建了3个同名的变量&#39; val&#39;。一个在全局上下文中,一个在obj中,另一个在obj的innerMethod中。 JavaScript通过从本地go全局上升范围链来解析特定上下文中的标识符。


可以区分this的几个地方

调用对象的方法

var status = 1;
var helper = {
    status : 2,
    getStatus: function () {
        return this.status;
    }
};

var theStatus1 = helper.getStatus(); //line1
console.log(theStatus1); //2

var theStatus2 = helper.getStatus;
console.log(theStatus2()); //1

当执行line1时,JavaScript为函数调用建立一个执行上下文(EC),将this设置为前一个&#34;之前所引用的对象。&#34; < / strong>即可。所以在最后一行你可以理解a()是在全局上下文中执行的window

使用构造函数

this可用于指代正在创建的对象

function Person(name){
    this.personName = name;
    this.sayHello = function(){
        return "Hello " + this.personName;
    }
}

var person1 = new Person('Scott');
console.log(person1.sayHello()); //Hello Scott

var person2 = new Person('Hugh');
var sayHelloP2 = person2.sayHello;
console.log(sayHelloP2()); //Hello undefined

执行新的Person()时,会创建一个全新的对象。调用Person并将其this设置为引用该新对象。

函数调用

function testFunc() {
    this.name = "Name";
    this.myCustomAttribute = "Custom Attribute";
    return this;
}

var whatIsThis = testFunc();
console.log(whatIsThis); //window

var whatIsThis2 = new testFunc();
console.log(whatIsThis2);  //testFunc() / object

console.log(window.myCustomAttribute); //Custom Attribute 

如果我们错过new个关键字,whatIsThis会引用它可以找到的最全局的上下文(window

使用事件处理程序

如果事件处理程序是内联的,this引用全局对象

<script type="application/javascript">
    function click_handler() {
        alert(this); // alerts the window object
    }
</script>

<button id='thebutton' onclick='click_handler()'>Click me!</button>

通过JavaScript添加事件处理程序时,this引用生成事件的DOM元素。


答案 15 :(得分:5)

“this”的值取决于执行函数的“context”。上下文可以是任何对象或全局对象,即窗口。

因此“this”的语义与传统的OOP语言不同。它会导致问题: 1.当函数传递给另一个变量时(很可能是一个回调); 2.当从类的成员方法调用闭包时。

在这两种情况下,都设置为窗口。

答案 16 :(得分:3)

Whould this有帮助吗? (javascript中对'this'的大多数混淆来自于它通常没有链接到你的对象,而是链接到当前的执行范围 - 这可能不是它的工作方式,但总是对我来说 - 请参阅文章以获得完整的解释)

答案 17 :(得分:3)

有关关键字

的一些信息

让我们在全局范围内将this关键字登录到控制台,但没有任何其他代码

console.log(this)

客户端/浏览器中,this关键字是一个全局对象,它是window

console.log(this === window) // true

服务器/节点/ JavaScript运行时中,this关键字也是一个全局对象,它是module.exports

console.log(this === module.exports) // true
console.log(this === exports) // true

请紧记exports只是对module.exports的引用

答案 18 :(得分:1)

就像这样使用Scope

  <script type="text/javascript" language="javascript">
$('#tbleName tbody tr').each(function{
var txt='';
txt += $(this).find("td").eq(0).text();
\\same as above but synatx different
var txt1='';
 txt1+=$('#tbleName tbody tr').eq(0).text();
alert(txt1)
});
</script>

txt1和txt的值相同 在上面的例子中 $(this)= $('#tbleName tbody tr')是相同的

答案 19 :(得分:1)

我对this的看法与我希望有帮助的其他答案不同。

查看JavaScript的一种方法是看到只有一种方法可以调用函数 1 。是

functionObject.call(objectForThis, arg0, arg1, arg2, ...);

始终为objectForThis提供一些值。

所有其他内容都是functionObject.call的语法糖

因此,其他所有内容都可以通过其翻译成functionObject.call的方式来描述。

如果仅调用函数,则this是“全局对象”,在浏览器中是窗口

function foo() {
  console.log(this);
}

foo();  // this is the window object

换句话说

foo();

被有效地翻译为

foo.call(window);

请注意,如果您使用严格模式,则this将是undefined

'use strict';

function foo() {
  console.log(this);
}

foo();  // this is the window object

这意味着

换句话说

foo();

被有效地翻译为

foo.call(undefined);

JavaScript中有+-*之类的运算符。还有一个点运算符为.

.运算符与右侧的函数和左侧的对象一起使用时,实际上意味着“将对象作为this传递给函数。

示例

const bar = {
  name: 'bar',
  foo() { 
    console.log(this); 
  },
};

bar.foo();  // this is bar

换句话说,bar.foo()转换为const temp = bar.foo; temp.call(bar);

请注意,函数的创建方式无关紧要(主要是...)。所有这些都会产生相同的结果

const bar = {
  name: 'bar',
  fn1() { console.log(this); },
  fn2: function() { console.log(this); },
  fn3: otherFunction,
};

function otherFunction() { console.log(this) };

bar.fn1();  // this is bar
bar.fn2();  // this is bar
bar.fn3();  // this is bar

这些都是语法糖

{ const temp = bar.fn1; temp.call(bar); }
{ const temp = bar.fn2; temp.call(bar); }
{ const temp = bar.fn3; temp.call(bar); }

原型皱纹是另一个皱纹。当您使用a.b时,JavaScript首先会在a直接引用的对象上查找属性b。如果在对象上未找到b,则JavaScript将在对象的原型中查找以找到b

定义对象原型的方法有很多种,2019年最常见的是class关键字。就this而言,这无关紧要。重要的是,如果它在对象a的对象b上找到了属性b,或者在原型链中找到了b,那么它在对象b中查找为函数,适用与上述相同的规则。函数call的引用将使用a方法,并将this作为objectForThis传递,如答案顶部所示。

现在。假设我们创建了一个在调用另一个函数之前先显式设置.的函数,然后使用function foo() { console.log(this); } function bar() { const objectForThis = {name: 'moo'} foo.call(objectForThis); // explicitly passing objectForThis } const obj = { bar, }; obj.bar(); (点)运算符

对其进行调用

call

翻译后使用obj.bar()const temp = obj.bar; temp.call(obj);变成bar。当我们输入foo函数时,我们将调用this,但是我们为objectForThis显式传递了另一个对象,因此,当我们到达foo bind时就是该内部对象。

这是=>bar函数有效执行的操作。它们是语法更多的糖。他们有效地构建了一个新的不可见函数,就像上面的this一样,它在调用指定的任何函数之前显式设置了this。对于绑定bind设置为您传递给function foo() { console.log(this); } const bar = foo.bind({name: 'moo'}); // bind created a new invisible function that calls foo with the bound object. bar(); // the objectForThis we are passing to bar here is ignored because // the invisible function that bind created will call foo with with // the object we bound above bar.call({name: 'other'});的任何值。

functionObject.bind

请注意,如果function bind(fn, objectForThis) { return function(...args) { return fn.call(objectForthis, ...args); }; } 不存在,我们可以像这样

function foo() {
  console.log(this);
}

const bar = bind(foo, {name:'abc'});

然后我们可以这样称呼

=>

箭头功能,const a = () => {console.log(this)}; 运算符是bind的语法糖

const tempFn = function() {console.log(this)}; 
const a = tempFn.bind(this);

相同
bind

就像objectForThis一样,创建了一个新的不可见函数,该函数用给定的bind绑定值调用给定函数,但是与this不同,要绑定的对象是隐式的。使用=>运算符时,const a = () => { console.log(this); } // this is the global object 都会发生这种情况。

所以,就像上面的规则

'use strict';
const a = () => { console.log(this); }  // this is undefined
function foo() {
  return () => { console.log(this); }
}

const obj = {
  foo,
};
const b = obj.foo();
b();
obj.foo()

const temp = obj.foo; temp.call(obj);转换为foo,这意味着obj中的箭头运算符会将b绑定到一个新的不可见函数,并返回分配给{{ 1}}。 b()将像b.call(window)b.call(undefined)一样调用foo创建的新的不可见函数。这个不可见的函数会忽略传递给它的this并将obj作为objectForThis`传递给箭头函数。

上面的代码翻译为

function foo() {
  function tempFn() {
    console.log(this);
  }
  return tempFn.bind(this);
}

const obj = {
  foo,
};
const b = obj.foo();
b.call(window or undefined if strict mode);

1 apply是类似于call

的另一个功能
functionName.apply(objectForThis, arrayOfArgs);

但是从ES6的概念上讲,您甚至可以将其翻译成

functionName.call(objectForThis, ...arrayOfArgs);

答案 20 :(得分:0)

摘要this Javascript:

  • this的值由如何不调用函数,在何处创建函数来确定!
  • 通常this的值由点左侧的对象确定。 (window在全球空间中)
  • 在事件侦听器中,this的值表示在其上调用事件的DOM元素。
  • 使用new关键字调用in函数时,this的值引用新创建的对象
  • 您可以使用以下函数操纵this的值:callapplybind

示例:

let object = {
  prop1: function () {console.log(this);}
}

object.prop1();   // object is left of the dot, thus this is object

const myFunction = object.prop1 // We store the function in the variable myFunction

myFunction(); // Here we are in the global space
              // myFunction is a property on the global object
              // Therefore it logs the window object
              
             

示例事件侦听器:

document.querySelector('.foo').addEventListener('click', function () {
  console.log(this);   // This refers to the DOM element the eventListener was invoked from
})


document.querySelector('.foo').addEventListener('click', () => {
  console.log(this);  // Tip, es6 arrow function don't have their own binding to the this v
})                    // Therefore this will log the global object
.foo:hover {
  color: red;
  cursor: pointer;
}
<div class="foo">click me</div>

示例构造函数:

function Person (name) {
  this.name = name;
}

const me = new Person('Willem');
// When using the new keyword the this in the constructor function will refer to the newly created object

console.log(me.name); 
// Therefore, the name property was placed on the object created with new keyword.

答案 21 :(得分:0)

JavaScript中的“ this”关键字是什么

此关键字指的是一个对象,该对象正在执行javascript代码的当前位。

换句话说,每个JavaScript函数在执行时都会引用其当前执行上下文,称为this。执行上下文意味着这里是函数的调用方式。

要理解此关键字,只需要知道如何,何时何地从何处调用函数,与如何在何处声明或定义函数无关。

function bike() {
  console.log(this.name);
}

var name = "Ninja";
var obj1 = { name: "Pulsar", bike: bike };
var obj2 = { name: "Gixxer", bike: bike };

bike();           // "Ninja"
obj1.bike();      // "Pulsar"
obj2.bike();      // "Gixxer"

在上述代码段中,bike()函数的工作是打印this.name,这意味着它正在尝试打印当前执行上下文的(i.e.this object)的name属性的值。

在上面的代码片段中,调用函数bike()时,它会打印“ Ninja”,因为未指定执行上下文,因此默认情况下它是全局上下文,并且在全局上下文中存在一个变量名称,其值是“忍者”。

在进行obj1().bike()调用的情况下,将打印“ Pulsar”,其背后的原因是函数bike()的执行上下文为obj1,因此this.name变为obj1.name。与obj2.bike()调用相同,其中函数bike()的执行上下文为obj2

“ this”的默认和隐式绑定

如果我们处于严格模式,则此关键字的默认值是不确定的,否则此关键字用作全局对象,称为此关键字的默认绑定。 (对于浏览器,默认为窗口对象。)

当我们将某个对象属性作为方法调用时,该对象成为该方法的该对象或执行上下文对象,这是此关键字的隐式绑定。

var obj1 = {
  name: "Pulsar",
  bike: function() {
    console.log(this.name);
  }
}
var obj2 = { name: "Gixxer", bike: obj1.bike };
var name = "Ninja";
var bike = obj1.bike;

bike();           // "Ninja"
obj1.bike();      // "Pulsar"
obj2.bike();      // "Gixxer"

在上面的代码片段中,函数调用bike()是默认绑定的示例。 obj1.bike()obj2.bike()是隐式绑定的示例。在这里,自行车功能被声明为obj1的一部分,但是无论我们在executeobj2.bike()时是什么,执行的上下文都是obj2,因此obj2.name会被打印出来。

重要的是要知道如何,何时何地调用该函数,而与声明函数的位置无关。

“ this”关键字的显式和固定绑定

如果我们将call和apply方法与调用函数一起使用,则这两个方法均将其第一个参数作为执行上下文。这就是这种约束力。

function bike() {
  console.log(this.name);
}

var name = "Ninja";
var obj = { name: "Pulsar" }

bike();           // "Ninja"
bike.call(obj);   // "Pulsar"

在上面的代码片段中,如果我们使用call()方法调用功能自行车,并将执行上下文对象obj作为第一个参数,则obj被分配给该对象,并且打印出“ Pulsar”,该文本不过是{{1 }}。称为此关键字的显式绑定。

在固定装订或硬装订中

无论从何处以及如何调用此对象,我们都可以强制使该对象始终相同。

obj.name

根据上面的代码片段,var bike = function() { console.log(this.name); } var name = "Ninja"; var obj1 = { name: "Pulsar" }; var obj2 = { name: "Gixxer" }; var originalBikeFun = bike; bike = function() { originalBikeFun.call(obj1); }; bike(); // "Pulsar" bike.call(obj2); // "Pulsar" bike()都调用打印“ Pulsar”,除了bike.call(obj2)之外什么都没有,这意味着功能自行车的执行上下文始终为obj1.name并且是因为obj1;这种绑定只是显式绑定的另一种形式,称为固定绑定。

答案 22 :(得分:0)

要正确理解“此”,必须了解上下文和范围以及它们之间的区别。

作用域:在javascript中,作用域与变量的可见性有关,作用域通过使用函数来实现。 (了解有关范围的更多信息)

上下文:上下文与对象有关。它是指功能所属的对象。当您使用JavaScript“ this”关键字时,它指向函数所属的对象。 例如,在函数内部,当您说:“ this.accoutNumber”时,是指属性“ accoutNumber”,该属性属于该函数所属的对象。

如果对象“ myObj”具有称为“ getMyName”的方法,则当在“ getMyName”内部使用JavaScript关键字“ this”时,它将引用“ myObj”。如果函数“ getMyName”是在全局范围内执行的,则“ this”是指窗口对象(严格模式下除外)。

现在让我们看一些示例:

    <script>
        console.log('What is this: '+this);
        console.log(this);
    </script>

浏览器输出中的Runnig上面的代码将: enter image description here

根据您在窗口对象上下文内的输出,还可以看到窗口原型引用了该对象。

现在让我们尝试一个函数内部:

    <script>
        function myFunc(){
            console.log('What is this: '+this);
            console.log(this);
        }
        myFunc();
    </script>

输出:

enter image description here 输出是相同的,因为我们在全局作用域中记录了“ this”变量,而在功能作用域中记录了该变量,我们没有更改上下文。在两种情况下,上下文都是相同的,与寡妇对象有关。

现在让我们创建自己的对象。在javascript中,您可以通过多种方式创建对象。

 <script>
        var firstName = "Nora";
        var lastName = "Zaman";
        var myObj = {
            firstName:"Lord",
            lastName:'Baron',
            printNameGetContext:function(){
                console.log(firstName + " "+lastName);
                console.log(this.firstName +" "+this.lastName);
                return this;
            }
        }

      var context = myObj.printNameGetContext();
      console.log(context);
    </script>

输出: enter image description here

因此,从上面的示例中,我们发现'this'关键字是指与myObj相关的新上下文,并且myObject也具有指向Object的原型链。

我们再举一个例子:

<body>
    <button class="btn">Click Me</button>
    <script>
        function printMe(){
            //Terminal2: this function declared inside window context so this function belongs to the window object.
            console.log(this);
        }
        document.querySelector('.btn').addEventListener('click', function(){
            //Terminal1: button context, this callback function belongs to DOM element 
            console.log(this);
            printMe();
        })
    </script>
</body>

输出: 有道理吧? (阅读评论) enter image description here

如果您无法理解上面的示例,请尝试使用我们自己的回调;

<script>
        var myObj = {
            firstName:"Lord",
            lastName:'Baron',
            printName:function(callback1, callback2){
                //Attaching callback1 with this myObj context
                this.callback1 = callback1;
                this.callback1(this.firstName +" "+this.lastName)
                //We did not attached callback2 with myObj so, it's reamin with window context by default
                callback2();
                /*
                 //test bellow codes
                 this.callback2 = callback2;
                 this.callback2();
                */
            }
        }
        var callback2 = function (){
            console.log(this);
        }
        myObj.printName(function(data){
            console.log(data);
            console.log(this);
        }, callback2);
    </script>

输出: enter image description here

现在让我们了解一下范围,自我,IIFE和这种行为

       var color = 'red'; // property of window
       var obj = {
           color:'blue', // property of window
           printColor: function(){ // property of obj, attached with obj
               var self = this;
               console.log('In printColor -- this.color: '+this.color);
               console.log('In printColor -- self.color: '+self.color);
               (function(){ // decleard inside of printColor but not property of object, it will executed on window context.
                    console.log(this)
                    console.log('In IIFE -- this.color: '+this.color);
                    console.log('In IIFE -- self.color: '+self.color); 
               })();

               function nestedFunc(){// decleard inside of printColor but not property of object, it will executed on window context.
                    console.log('nested fun -- this.color: '+this.color);
                    console.log('nested fun -- self.color: '+self.color);
               }

               nestedFunc(); // executed on window context
               return nestedFunc;
           }
       };

       obj.printColor()(); // returned function executed on window context
   </script> 

输出非常棒,对吗? enter image description here

答案 23 :(得分:-1)

简单答案:

“此”关键字始终取决于调用的上下文。它们在下面提到。

  1. 使用新关键字调用了功能

    如果使用NEW关键字调用该函数,则此函数将绑定到新创建的对象。

    function Car(){
      this.name="BMW";
    }
    const myCar=new Car();
    myCar.name; // output "BMW"
    

    在上面,它将绑定到“ myCar”对象

  2. 使用呼叫和应用方法明确调用功能。

    在这种情况下,THIS将绑定到显式传递给函数的对象。

    var obj1={"name":"bond"};
    function printMessage(msg){
        return msg+" "+this.name;
    }
    const message=printMessage.call(obj1,"my name is ");
    console.log(message); //HERE THIS WILL BE BOUND TO obj1 WHICH WE PASSED EXPLICITLY. SAME FOR APPLY METHOD ALSO.
    
  3. 如果隐式调用了功能,则该功能将绑定到该对象上

    var obj1={
       "name":"bond",
        getName: function () {
                    return this.name;
                 }
    };
    const newname=obj1.getName();
    console.log(newname); //HERE THIS WILL BE BOUND TO obj1(WHITCHEVER OBJECT IS MENTIONED BEFORE THE DOT THIS WILL BE BOUND TO THAT)
    
  4. 在没有任何上下文的情况下调用功能,那么它将被限制在全球范围内

    const util = {
       name: 'Utility',
       getName: function () {
                    return this.name;
    };
    
    const getName=util.getName;
    const newName=getName();
    console.log(newName); // IF THIS EXECUTED IN BROWSER THIS WILL BE  BOUND TO WINDOW OBJECT. IF THIS EXECUTED IN SERVER THIS WILL BE BOUND TO GLOBAL OBJECT
    
  5. 在严格模式下将无法定义

    function setName(name){
        "use strict"
        return this.name;
    }
    setName(); //WILL BE ERROR SAYING name IS UNDEFINED.