我希望找到一个“this”关键字的明确解释,以及如何正确使用它。

它的行为似乎很奇怪,我不完全明白为什么。

这是如何工作的,何时使用?


当前回答

这是我见过的最好的解释:清晰地理解JavaScripts

此引用总是指(并保持)object-一个单独的对象,通常用于函数或方法,尽管它可以在全局范围请注意,当我们使用strict模式时在全局函数和匿名函数中未定义绑定到任何对象。

有四种情况可能会令人困惑:

当我们传递一个方法(使用此方法)作为参数用作回调函数时。当我们使用内部函数(闭包)时。需要注意的是,闭包不能通过使用this关键字访问外部函数的this变量,因为this变量只能由函数本身访问,而不能由内部函数访问。当依赖于此的方法被分配给跨上下文的变量时,在这种情况下,它引用了另一个对象,而不是最初预期的对象。与bind、apply和call方法一起使用时。

他给出了代码示例、解释和解决方案,我认为这很有帮助。

其他回答

这是我见过的最好的解释:清晰地理解JavaScripts

此引用总是指(并保持)object-一个单独的对象,通常用于函数或方法,尽管它可以在全局范围请注意,当我们使用strict模式时在全局函数和匿名函数中未定义绑定到任何对象。

有四种情况可能会令人困惑:

当我们传递一个方法(使用此方法)作为参数用作回调函数时。当我们使用内部函数(闭包)时。需要注意的是,闭包不能通过使用this关键字访问外部函数的this变量,因为this变量只能由函数本身访问,而不能由内部函数访问。当依赖于此的方法被分配给跨上下文的变量时,在这种情况下,它引用了另一个对象,而不是最初预期的对象。与bind、apply和call方法一起使用时。

他给出了代码示例、解释和解决方案,我认为这很有帮助。

这是JavaScript中一个被误解的概念,因为它在不同地方的行为几乎不同。简单地说,这是指我们当前正在执行的函数的“所有者”。

这有助于获取我们使用的当前对象(也称为执行上下文)。如果您了解当前函数在哪个对象中执行,那么您可以很容易地了解这是什么当前函数

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个同名“val”的变量。一个在全局上下文中,一个在obj内部,另一个在obj的innerMethod内部。JavaScript通过从本地到全局的作用域链来解析特定上下文中的标识符。


很少有地方可以区分这一点

调用对象的方法

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

当执行第1行时,JavaScript为函数调用建立一个执行上下文(EC),将其设置为最后一个“.”之前引用的对象。因此在最后一行中,您可以理解a()是在全局上下文(即窗口)中执行的。

使用构造函数

这可用于引用正在创建的对象

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

当执行new 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 

如果我们错过了新的关键字,whatIsThis指的是它能找到的最全局的上下文(window)

使用事件处理程序

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

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

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

通过JavaScript添加事件处理程序时,这是指生成事件的DOM元素。


您还可以使用.apply().call()和.bind()操作上下文JQuery代理是另一种方法,您可以使用它来确保函数中的值符合您的要求。(检查了解$.proxy()、jQuery.proxy)用法)var that=this在JavaScript中意味着什么

javascript中的每个执行上下文都有一个this参数,该参数由以下参数设置:

如何调用函数(包括作为对象方法、调用和应用的使用、new的使用)绑定的使用箭头函数的词汇(它们采用外部执行上下文的this)代码是严格模式还是非严格模式是否使用eval调用代码

可以使用func.all、func.apply或func.bind设置此值。

默认情况下,当在DOM元素上引发事件后调用监听器时,函数的这个值就是DOM元素,这让大多数初学者感到困惑。

jQuery使用jQuery.proxy进行更改变得很简单。

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

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

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

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

现在让我们看看一些示例:

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

在浏览器输出中运行abobve代码将:

根据窗口对象上下文中的输出,也可以看到窗口原型引用了对象。

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

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

输出:有道理吧?(阅读评论)

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

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

输出:

现在,让我们了解范围、自我、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> 

输出非常棒,对吧?

由于这篇文章的篇幅有所增加,我为读者整理了一些新的观点。

这个值是如何确定的?

我们使用这个词的方式与我们在英语等自然语言中使用代词的方式类似:“约翰跑得很快,因为他正在赶火车。”相反,我们可以写“……约翰正在赶火车”。

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

在对象调用定义它的函数之前,不会为其赋值。在全局范围中,所有全局变量和函数都在窗口对象上定义。因此,这在全局函数中引用(并且具有的值)全局窗口对象。

当使用strict时,在未绑定到任何对象的全局函数和匿名函数中,它的值为undefined。

this关键字在以下情况下最容易被误解:1)我们借用了一个使用this的方法,2)我们将一个使用它的方法分配给一个变量,3)使用this的函数作为回调函数传递,4)这在闭包内部使用-一个内部函数。(2)

未来是什么

在ECMA脚本6中定义,箭头函数采用来自封闭(函数或全局)范围。

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)


参考文献:

凯尔·辛普森(Kyle Simpson)的《this&Object Prototypes》。©2014 Getify解决方案。javascriptissxy.com-http://goo.gl/pvl0GX 安格斯·克罗尔http://goo.gl/Z2RacU