"this"关键字是如何工作的,以及何时应该使用它?

1489

我希望找到一个清晰的解释,“this”关键字的作用是什么,以及如何正确使用它。

它似乎表现得很奇怪,我不完全明白为什么。

this如何工作,应该在什么情况下使用?


22个回答

1

总结 this Javascript:

  • this的值取决于函数的调用方式,而不是它创建的位置!
  • 通常情况下,this的值由点号左侧的对象决定。(在全局空间中为window
  • 在事件监听器中,this的值指向调用事件的DOM元素。
  • 当使用new关键字调用函数时,this的值指向新创建的对象。
  • 您可以使用callapplybind函数来操作this的值。

示例:

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.


0

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

范围:在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>

在浏览器中运行上面的代码会输出: {{link1:在此输入图片描述}}
根据输出,你在window对象的上下文中,还可以看到window原型引用了Object。
现在让我们尝试在一个函数内部:
    <script>
        function myFunc(){
            console.log('What is this: '+this);
            console.log(this);
        }
        myFunc();
    </script>

输出:

输入图像描述 输出结果相同,因为我们在全局范围内记录了“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>

输出: 在此输入图像描述

因此,从上面的例子中,我们发现'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>

输出: 有道理吧?(阅读评论) {{link1:输入图像描述}}

如果您难以理解上面的示例,让我们尝试使用自己的回调函数;

<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>

输出: 在此输入图片描述

现在让我们了解作用域、Self、IIFE和THIS的行为方式

       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> 

输出结果很棒,对吧? 输入图像描述


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