关于javascript:“this”关键字如何工作?

How does the “this” keyword work?

我注意到,似乎没有一个明确的解释说明什么是this关键字,以及它是如何正确(和错误)地在堆栈溢出站点的javascript中使用的。

我亲眼目睹了一些非常奇怪的行为,却不明白为什么会发生这种事。

this是如何工作的?应该何时使用?


我建议先阅读一下MikeWest在javascript(mirror)中的文章范围。这是一个极好的、友好的介绍,介绍了Javascript中的this和作用域链的概念。好的。

一旦你开始习惯了this,规则实际上相当简单。ECMAScript 5.1标准定义了this:好的。

§11.1.1 The this keyword

The this keyword evaluates to the value of the ThisBinding of the current execution context

Ok.

这个绑定是JavaScript解释器在评估JavaScript代码时维护的,比如一个特殊的CPU寄存器,它保存对对象的引用。当仅在三种不同情况中的一种情况下建立执行上下文时,解释器将更新此绑定:好的。1。初始全局执行上下文

这是在顶层评估的javascript代码的情况,例如,当直接在中时:好的。

1
2
3
4
5
  alert("I'm evaluated in the initial global execution context!");

  setTimeout(function () {
      alert("I'm NOT evaluated in the initial global execution context.");
  }, 1);

在初始全局执行上下文中评估代码时,将此绑定设置为全局对象window(§10.4.1.1)。好的。输入评估代码

  • …直接打电话给eval()。此绑定保持不变;它与调用执行上下文的此绑定的值相同(§10.4.2(2)(a))。好的。

  • …如果不是直接打电话给eval()。将此绑定设置为全局对象,如同在初始全局执行上下文(§10.4.2(1))中执行一样。好的。

§15.1.2.1.1定义了直接调用eval()是什么。基本上,eval(...)是一个直接调用,而类似(0, eval)(...)var indirectEval = eval; indirectEval(...);是对eval()的间接调用。在javascript中看到Chuckj对(1,eval)("this")和eval("this")的回答吗?以及Dmitry Soshnikov的ECMA-262-5。第2章。严格模式。当你可能使用一个间接的eval()呼叫时。好的。输入功能代码

调用函数时会发生这种情况。如果在对象上调用函数,例如在obj.myMethod()或等效的obj["myMethod"]()中,则将此绑定设置为该对象(在示例中为obj;在§13.2.1)。在大多数其他情况下,此绑定被设置为全局对象(§10.4.3)。好的。

之所以写"在大多数其他情况下",是因为有八个ecmascript 5内置函数允许在参数列表中指定此绑定。这些特殊函数采用所谓的thisArg,当调用函数(§10.4.3)时,它就成为这个绑定。好的。

这些特殊的内置功能包括:好的。

  • Function.prototype.apply( thisArg, argArray )
  • Function.prototype.call( thisArg [ , arg1 [ , arg2, ... ] ] )
  • Function.prototype.bind( thisArg [ , arg1 [ , arg2, ... ] ] )
  • Array.prototype.every( callbackfn [ , thisArg ] )
  • Array.prototype.some( callbackfn [ , thisArg ] )
  • Array.prototype.forEach( callbackfn [ , thisArg ] )
  • Array.prototype.map( callbackfn [ , thisArg ] )
  • Array.prototype.filter( callbackfn [ , thisArg ] )

对于Function.prototype函数,在函数对象上调用它们,但不将thisbinding设置为函数对象,而是将thisbinding设置为thisArg。好的。

Array.prototype函数的情况下,在执行上下文中调用给定的callbackfn,如果提供此绑定,则将其设置为thisArg;否则,将其设置为全局对象。好的。

这些是普通JavaScript的规则。当您开始使用javascript库(例如jquery)时,您可能会发现某些库函数操作EDOCX1的值(0)。这些JavaScript库的开发人员这样做是因为它倾向于支持最常见的用例,而库的用户通常认为这种行为更方便。当将引用this的回调函数传递给库函数时,您应该参考文档以获得调用函数时this的值的任何保证。好的。

如果您想知道一个javascript库如何处理EDOCX1的值(0),那么这个库只是使用一个接受thisArg的内置javascript函数。您也可以使用回调函数和thisArg编写自己的函数:好的。

1
2
3
4
function doWork(callbackfn, thisArg) {
    //...
    if (callbackfn != null) callbackfn.call(thisArg);
}

我还没有提到一个特殊的案例。通过new操作符构造新对象时,javascript解释器创建一个新的空对象,设置一些内部属性,然后对新对象调用构造函数函数。因此,当在构造函数上下文中调用函数时,this的值是解释器创建的新对象:好的。

1
2
3
4
5
6
7
8
function MyType() {
    this.someData ="a string";
}

var instance = new MyType();
// Kind of like the following, but there are more steps involved:
// var instance = {};
// MyType.call(instance);

箭头函数

arrow函数(在ecma6中引入)更改EDOCX1的作用域〔0〕。参见现有的规范问题,箭头函数与函数声明/表达式:它们是否等价/可交换?更多信息。但简而言之:好的。

Arrow functions don't have their own this.... binding.
Instead, those identifiers are resolved in the lexical scope like any
other variable. That means that inside an arrow function, this...refer(s) to the values of this in the environment
the arrow function is defined in.

Ok.

为了好玩,用一些例子来测试你的理解

要显示答案,请将鼠标移到淡黄色框上。好的。

  • 在标记的行上,this的值是多少?为什么?好的。

    window—标记行在初始全局执行上下文中进行评估。好的。< /块引用>

    1
    2
    3
    if (true) {
        // What is `this` here?
    }
  • 执行obj.staticFunction()时,标记行的this值是多少?为什么?好的。

    obj—当对对象调用函数时,此绑定被设置为对象。好的。< /块引用>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var obj = {
        someData:"a string"
    };

    function myFun() {
        return this // What is `this` here?
    }

    obj.staticFunction = myFun;

    console.log("this is window:", obj.staticFunction() == window);
    console.log("this is obj:", obj.staticFunction() == obj);

    好的。

  • 在标记的行上,this的值是多少?为什么?好的。

    window

    在本例中,javascript解释器输入函数代码,但由于没有对对象调用myFun/obj.myMethod,因此将此绑定设置为window

    这与python不同,在python中,访问方法(obj.myMethod创建绑定方法对象。好的。< /块引用>

    1
    2
    3
    4
    5
    6
    7
    8
    var obj = {
        myMethod: function () {
            return this; // What is `this` here?
        }
    };
    var myFun = obj.myMethod;
    console.log("this is window:", myFun() == window);
    console.log("this is obj:", myFun() == obj);

    好的。

  • 在标记的行上,this的值是多少?为什么?好的。

    window

    这件事很棘手。评估评估评估代码时,thisobj。但是,在eval代码中,没有对对象调用myFun,因此调用时将此绑定设置为window。好的。< /块引用>

    1
    2
    3
    4
    5
    6
    7
    8
    function myFun() {
        return this; // What is `this` here?
    }
    var obj = {
        myMethod: function () {
            eval("myFun()");
        }
    };
  • 在标记的行上,this的值是多少?为什么?好的。

    obj

    myFun.call(obj);正在调用特殊的内置函数Function.prototype.call(),它接受thisArg作为第一个参数。好的。< /块引用>

    1
    2
    3
    4
    5
    6
    7
    8
    function myFun() {
        return this; // What is `this` here?
    }
    var obj = {
        someData:"a string"
    };
    console.log("this is window:", myFun.call(obj) == window);
    console.log("this is obj:", myFun.call(obj) == obj);

    好的。

  • 好啊。


    与其他语言相比,在javascript中,this关键字的行为有所不同。在面向对象语言中,this关键字是指类的当前实例。在javascript中,this的值主要由函数的调用上下文(context.function()和调用位置决定。好的。

    1。在全局上下文中使用时好的。

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

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

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

    1
    2
    3
    4
    5
    function f1()
    {
       return this;
    }
    document.write(f1());  //[object Window]

    上面的f1是一种全局对象的方法。因此,我们也可以在window对象上称之为:好的。

    1
    2
    3
    4
    5
    6
    function f()
    {
        return this;
    }

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

    2。在对象方法内部使用时好的。

    在对象方法中使用this关键字时,this绑定到"立即"封闭对象。好的。

    1
    2
    3
    4
    5
    6
    7
    var obj = {
        name:"obj",
        f: function () {
            return this +":" + this.name;
        }
    };
    document.write(obj.f());  //[object Object]:obj

    上面我已经用双引号将单词immediate括起来了。要强调的是,如果将对象嵌套在另一个对象中,那么this将绑定到直接父对象。好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var obj = {
        name:"obj1",
        nestedobj: {
            name:"nestedobj",
            f: function () {
                return this +":" + this.name;
            }
        }            
    }

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var obj1 = {
        name:"obj1",
    }

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

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

    三。调用无上下文函数时好的。

    当您在没有任何上下文(即不在任何对象上)调用的函数内部使用this时,它绑定到全局对象(浏览器中的window(即使该函数是在对象内部定义的)。好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    /*********************************************************************
      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指向正在构造的新对象。好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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引用了调用该方法的对象,就像该方法是在对象上定义的一样。好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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设置为fun()内的this的值,并称argsArrayfun()传递元素为其参数。
    • fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])—将obj1设置为fun()内的this的值,并称fun()通过arg1, arg2, arg3, ...作为其论据。
    • fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])—返回对函数fun的引用,其中thisinside fun绑定到obj1上,fun的参数绑定到指定的arg1, arg2, arg3,...上。
    • 到目前为止,applycallbind之间的差别肯定已经很明显了。apply允许指定参数作为类似数组的对象,即具有数字length属性和相应的非负整数属性的对象。而call允许直接为函数指定参数。applycall都立即在指定的上下文和指定的参数中调用函数。另一方面,bind只返回绑定到指定this值和参数的函数。我们可以通过将返回函数赋给变量来捕获对它的引用,稍后我们可以随时调用它。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    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</wyn>

    7。this内部事件处理程序好的。

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

    我建议最好在jfiddle中尝试一下。好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
        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);  


    Using `this`"directly" inside event handler or event property
    <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>

    Using `this`"indirectly" inside event handler or event property
    <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>

    好啊。


    javascript的this简单函数调用

    考虑以下功能:

    1
    2
    3
    4
    5
    function foo() {
        console.log("bar");
        console.log(this);
    }
    foo(); // calling the function

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

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

    如果在node.js等环境中运行这段代码,this将引用应用程序中的全局变量。

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

    在下面的例子中,我们将看到如何操纵this的值。

    对对象调用函数

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

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

    如果Object包含持有Function的属性,则该属性称为方法。调用此方法时,它的this变量将始终设置为它所关联的Object变量。严格模式和非严格模式都是如此。

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

    1
    2
    3
    4
    5
    // continuing with the previous code snippet

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

    考虑到更普遍的实际情况:

    1
    2
    3
    4
    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中的构造函数函数:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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关键字时会发生什么。

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

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

    函数调用函数:callapply

    所以,是的,因为Function也是Objects(实际上是javascript中的第一类变量),所以即使函数也有一些方法……嗯,功能本身。

    所有函数都继承自全局Function,它的许多方法中有两种是callapply,它们都可以用来操作调用它们的函数中this的值。

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

    这是使用call的典型示例。它基本上取第一个参数,在函数foo中设置this作为对thisArg的引用。传递给call的所有其他参数都作为参数传递给函数foo。因此上面的代码将记录myobj:"is cool


    "这"是关于范围的。每个函数都有自己的作用域,因为JS中的所有内容都是一个对象,所以即使函数也可以使用"this"将一些值存储到自身中。oop 101告诉我们"这"只适用于对象的实例。因此,每次执行一个函数时,该函数的一个新"实例"都具有"this"的新含义。

    大多数人在匿名闭包函数中尝试使用"this"时会感到困惑,比如:

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

    因此,在这里,在每个()中,"this"不包含您期望的"value"(从它上面的

    1
    this.value = value;

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

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

    试试看,你会开始喜欢这种编程模式的


    由于这篇文章的内容增加了,我为this主题的新读者编写了一些要点。

    如何确定this的值?

    我们使用这个词的方式和我们使用英语等自然语言的代词的方式类似:"约翰跑得很快,因为他想赶火车。"相反,我们可以写"约翰想赶火车"。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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

    当:1)我们借用一个使用this的方法,2)我们将一个使用this的方法分配给一个变量,3)一个使用this的函数作为回调函数传递,4)this在一个闭包内使用,这是一个内部函数。(2)

    table

    什么决定了未来?

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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!

    虽然arrow函数提供了一种使用bind()的替代方法,但需要注意的是,它们实际上是在禁用传统的this机制,从而有利于更广泛地理解词汇范围。(1)

    参考文献:

  • 此&对象原型,由Kyle Simpson提供。?2014 Getify解决方案。
  • javascriptissxy.com-http://goo.gl/pvl0gx
  • 安格斯·克罗尔-http://goo.gl/z2racu

  • javascript中的this总是指正在执行的函数的"所有者"。

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

    如果我做到了

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

    element.onclick = someKindOfFunction;

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

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


    javascript中的每个functionexecution context都有一个scopecontextthis parameter that is set by:

  • 如何调用函数(包括作为对象方法、使用call和apply、使用new)
  • 绑定的使用
  • 在词汇上表示箭头函数(它们采用其外部执行上下文的这一点)
  • 无论作用域上下文是什么,都由"this"引用。

    您可以使用func.callfunc.applyfunc.bind更改该值。

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

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


    这是JavaScriptthis的一个好来源。

    以下是总结:

    • 全球这

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

      1
      2
      3
      4
      5
      <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

      1
      2
      3
      4
      5
      6
      7
      >this
        { ArrayBuffer: [Function: ArrayBuffer],
          Int8Array: { [Function: Int8Array] BYTES_PER_ELEMENT: 1 },
          Uint8Array: { [Function: Uint8Array] BYTES_PER_ELEMENT: 1 },
          ...
      >global === this
       true

      在从脚本执行的node中,全局范围内的this以空对象开始。与global不同

      1
      2
      3
      \\test.js
      console.log(this);  \\ {}
      console.log(this === global); \\ fasle
    • 函数此

    除了在dom事件处理程序的情况下,或者当提供thisArg时(见下文),在节点和浏览器中使用this在一个不使用new调用的函数中引用全局作用域…

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <script type="text/javascript">
        foo ="bar";

        function testThis() {
          this.foo ="foo";
        }

        console.log(this.foo); //logs"bar"
        testThis();
        console.log(this.foo); //logs"foo"

    如果您使用use strict;,在这种情况下,this将是undefined

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <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

    如果使用new调用函数,this将是一个新的上下文,它不会引用全局this

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <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"
    • 原型本

    您创建的函数将成为函数对象。它们会自动获得一个特殊的prototype属性,您可以将该属性赋值给它。通过使用new调用函数来创建实例时,可以访问分配给prototype属性的值。您可以使用this访问这些值。

    1
    2
    3
    4
    5
    6
    7
    8
    function Thing() {
      console.log(this.foo);
    }

    Thing.prototype.foo ="bar";

    var thing = new Thing(); //logs"bar"
    console.log(thing.foo);  //logs"bar"

    prototype上分配数组或对象通常是错误的。如果希望每个实例都有自己的数组,请在函数中创建它们,而不是在原型中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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创建的实例不同。

    1
    2
    3
    4
    5
    6
    7
    8
    var obj = {
        foo:"bar",
        logFoo: function () {
            console.log(this.foo);
        }
    };

    obj.logFoo(); //logs"bar"
    • DOM事件

    在HTML DOM事件处理程序中,this始终是对事件附加到的DOM元素的引用。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function Listener() {
        document.getElementById("foo").addEventListener("click",
           this.handleClick);
    }
    Listener.prototype.handleClick = function (event) {
        console.log(this); //logs""
    }

    var listener = new Listener();
    document.getElementById("foo").click();

    除非你在上下文中

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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();
    • 这个HTML

    在可以放置javascript的HTML属性中,this是对元素的引用。

    1
    2
    <script type="text/javascript">
    document.getElementById("foo").click(); //logs <div id="foo"...
    • 这个时代

    您可以使用eval访问this

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function Thing () {
    }
    Thing.prototype.foo ="bar";
    Thing.prototype.logFoo = function () {
        eval("console.log(this.foo)"); //logs"bar"
    }

    var thing = new Thing();
    thing.logFoo();
    • 用这个

    您可以使用withthis添加到当前作用域,以读取和写入this上的值,而无需显式引用this

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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"
    • jQuery

    jquery在很多地方都会让this引用一个dom元素。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <script type="text/javascript">
    $(".foo").each(function () {
        console.log(this); //logs <div class="foo...
    });
    $(".foo").on("click", function () {
        console.log(this); //logs <div class="foo...
    });
    $(".foo").each(function () {
        this.click();
    });

    关于this最详细、最全面的文章可能是:

    在javascript中温和地解释"this"关键字

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

    在识别this时,不要问自己:

    Where is this taken from?

    但一定要问问自己:

    How is the function invoked?

    对于箭头函数(上下文透明的特殊情况),请自问:

    What value has this where the arrow function is defined?

    这种心态在处理this时是正确的,可以使你免于头痛。


    关于"this"关键字在JavaScript中的解释方式有很多困惑。希望这篇文章能让所有这些都一劳永逸。还有更多。请仔细阅读整篇文章。请注意,这篇文章很长。好的。

    不管使用它的上下文是什么,"这个"总是引用JavaScript中的"当前对象"。但是,根据上下文,"当前对象"是不同的。上下文可能正好是以下6个上下文中的1个:好的。

  • 全局(即所有功能之外)
  • 在直接的"非绑定函数"调用中(即未通过调用functionname.bind绑定的函数)
  • 在通过functionname.call和functionname.apply的间接"非绑定函数"调用中
  • 在"bound function"调用中(即通过调用functionname.bind绑定的函数)
  • 通过"新建"创建对象时
  • 内联DOM事件处理程序内部
  • 下面逐一描述每个上下文:好的。

  • 全局上下文(即在所有函数之外):好的。

    在所有功能之外(即在全局上下文中),"当前对象(因此"this"的值)始终是浏览器的"窗口"对象。好的。

  • 内部直接"非绑定函数"调用:好的。

    在直接的"非绑定函数"调用中,调用函数调用成为"当前对象"(因此"this"的值)。如果在没有显式当前对象的情况下调用函数,则当前对象是"window"对象(对于非严格模式)或未定义(对于严格模式)。中定义的任何函数(或变量)全局上下文自动成为"窗口"对象的属性。例如,假设函数在全局上下文中定义为好的。

    1
    2
    3
    function UserDefinedFunction(){
        alert(this)
        }

    它将成为窗口对象的属性,就好像您已经定义了它作为好的。

    1
    2
    3
    window.UserDefinedFunction=function(){
      alert(this)
    }

    在"非严格模式"下,直接通过"userDefinedFunction()"调用/调用此函数将自动调用/调用它是"window.userDefinedFunction()"使"window"成为"用户定义函数"中的"当前对象"(以及"this"的值)。在"非严格模式"中调用此函数将导致以下结果好的。

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

    在"严格模式"下,直接通过"userDefinedFunction()"将"not"自动调用/调用它为"window.userDefinedFunction()",因此"current"对象"(和"this"的值)"用户定义函数"应未定义。在"严格模式"中调用此函数将导致以下结果好的。

    1
    UserDefinedFunction() // displays undefined

    但是,使用window对象显式调用它将导致以下好的。

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

    让我们来看另一个例子。请看下面的代码好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     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

    在上面的示例中,我们看到当"userDefinedFunction"是通过O1调用,"this"的值为O1,并且显示其属性"A"和"B"的值。价值其中"c"和"d"如o1所示未定义。不定义这些属性好的。

    同样,当通过O2调用"userdefinedFunction"时,"this"获取O2值,并显示其属性"c"和"d"的值。"a"和"b"的值显示为未定义,因为O2没有定义这些属性。好的。

  • 在通过functionname.call和functionname.apply的间接"非绑定函数"调用中:好的。

    当通过调用"非绑定函数"时functionname.call或functionname.apply,将"当前对象"(因此"this")的值设置为传递给call/apply的"this"参数(第一个参数)。下面的代码演示了相同的内容。好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    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

    上面的代码清楚地显示了"this"值对于任何"non"绑定函数"可以通过调用/应用进行更改。此外,如果"this"参数未显式传递给call/apply,"current object"(因此,"this")的值在非严格模式下设置为"window",在严格模式下设置为"undefined"。好的。

  • 在"bound function"调用中(即通过调用functionname.bind绑定的函数):好的。

    绑定函数是其"this"值固定的。下面的代码演示了"this"在有界函数好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    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

    如上述代码所示,"此"值表示任何"绑定函数"不能通过调用/应用更改。此外,如果"this"参数未显式传递给bind,"当前对象"(因此,"this")的值在非严格模式和"未定义"严格模式。还有一件事。绑定已绑定的函数不会更改"this"的值。它仍然被设置为第一个绑定函数设置的值。好的。

  • 通过"新建"创建对象时:好的。

    在构造函数函数内部,"当前对象"(因此"this")引用当前正在创建的对象通过"new"而不管函数的绑定状态如何。然而如果构造函数是绑定函数,则应使用作为绑定函数集的预定义参数集。好的。

  • 在内联DOM事件处理程序内:好的。

    请看下面的HTML代码段好的。

    1
    2
    <button onclick='this.style.color=white'>Hello World</button>
    Hello World

    上述示例中的"this"指的是"button"元素和"DIV"元素。好的。

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

    在第二个示例中,单击"div"元素时,它应用第二个参数调用OnDivClick函数引用单击的DIV元素。然而,"这个"的价值OnDivClick中不应引用单击的DIV元素。应设置为"窗口对象"或分别在非严格和严格模式下"未定义"(如果OnDivClick是未绑定函数)或设置为预定义的绑定值(如果OnDivClick是绑定函数)好的。

  • 以下是对整篇文章的总结好的。

  • 在全局上下文中,"this"始终指"window"对象好的。

  • 每当调用函数时,都会在对象("当前对象")。如果未显式提供当前对象,当前对象是非严格的"窗口对象"模式和"未定义"默认为严格模式。好的。

  • 非绑定函数中"this"的值是对调用该函数的上下文中的对象的引用("当前对象")。好的。

  • 非绑定函数中"this"的值可以由重写调用并应用函数的方法。好的。

  • 对于绑定函数,"this"的值是固定的,不能由函数的调用和应用方法重写。好的。

  • 绑定和已绑定函数不会更改"this"的值。它仍然被设置为第一个绑定函数设置的值。好的。

  • 构造函数中"this"的值是已创建并初始化好的。

  • 内联DOM事件处理程序中"this"的值是引用为其提供事件处理程序的元素。好的。

  • 好啊。


    丹尼尔,太棒了!在事件处理程序的情况下,这里有两个单词和一个很好的this执行上下文指针列表。

    换句话说,在javascript中,this指向当前函数运行的对象(或从其执行上下文运行当前函数的对象),该对象始终是只读的,您无论如何都不能设置它(这样的尝试最终会导致"赋值中的左侧无效"消息)。

    对于事件处理程序:内联事件处理程序(如)重写之前和之前附加的任何其他处理程序,因此要小心,最好不要进行内联事件委托。感谢Zara Alaverdian,他通过一场不同的辩论激励我列出了这个例子。

    • 6
    • 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 :)

    这是我见过的最好的解释。清楚地理解javascripts

    The this reference ALWAYS refers to (and holds the value of) an
    object—a singular object—and it is usually used inside a function or a
    method, although it can be used outside a function in the global
    scope. Note that when we use strict mode, this holds the value of
    undefined in global functions and in anonymous functions that are not
    bound to any object.

    有四种情况会让人困惑:

  • 当我们传递一个方法(使用这个方法)作为参数来用作回调函数时。
  • 另一个被误解的例子是我们使用一个内部方法(闭包)。需要注意的是,闭包不能使用this关键字访问外部函数的this变量,因为该变量只能由函数本身访问,而不能由内部函数访问。
  • 当一个方法被分配给一个变量时使用这个方法。如果我们将使用此值的方法赋给变量,则此值将绑定到另一个对象
  • 在使用bind、apply和call方法时使用它。
  • 他给出了代码示例、解释和我认为非常有用的代码修复。


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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;

    如果您不完全理解JS,那么很难很好地掌握它,或者写得比它中的任何琐碎内容都多。你不能只花一点点钱去尝试一下:)我认为开始使用JS的最好方法是首先观看Douglas Crockford的视频讲座-http://yuiblog.com/crockford/,它涵盖了这个和那个,以及JS的所有其他方面。


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

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

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


    this是javascript中被误解的概念之一,因为它在不同的地方的行为几乎没有什么不同。简单地说,this是指我们当前正在执行的函数的"所有者"。

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    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内部。javascript通过从本地go global向上搜索作用域链来解析特定上下文中的标识符。

    很少有地方能区分this

    调用对象的方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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),将this设置为最后一个"."之前的任何对象所引用的对象。所以在最后一行中,您可以理解,a()是在全球环境中执行的,即window

    有建设者

    this可用于引用正在创建的对象。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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设置为引用该新对象。

    函数调用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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引用全局对象

    1
    2
    3
    4
    5
    6
    7
    <script type="application/javascript">
        function click_handler() {
            alert(this); // alerts the window object
        }


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

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

    • 您还可以使用.apply().call().bind()来操纵上下文。
    • jquery代理是另一种方法,可以用来确保函数中的这个值是您想要的值。(检查是否理解$.proxy()、jquery.proxy()的用法)
    • 在javascript中,var that = this是什么意思?

    关于这个关键字的一些信息

    让我们将this关键字记录到全局范围内的控制台,不需要再使用任何代码,但是

    1
    console.log(this)

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

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

    在server/node/javascript运行时,this关键字也是一个全局对象,它是module.exports关键字。

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

    记住,exports只是对module.exports的引用。


    这对谁有帮助?(在javascript中,"this"最令人困惑的是,它通常不链接到您的对象,而是链接到当前的执行范围——这可能并不完全是它的工作方式,但对我来说总是这样——请参阅本文以获得完整的解释)


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

    查看javascript的一种方法是查看只有一种方法可以调用函数1。它是好的。

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

    总是有一些值提供给objectForThis。好的。

    其他的都是functionObject.call的语法糖。好的。

    所以,其他一切都可以用它如何翻译成functionObject.call来描述。好的。

    如果您只是调用一个函数,那么this是"全局对象",在浏览器中是窗口。好的。

    1
    2
    3
    4
    5
    function foo() {
      console.log(this);
    }

    foo();  // this is the window object

    好的。

    换言之,好的。

    1
    foo();

    被有效地转化为好的。

    1
    foo.call(window);

    请注意,如果使用严格模式,那么this将是undefined。好的。

    1
    2
    3
    4
    5
    6
    7
    'use strict';

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

    foo();  // this is the window object

    好的。

    这意味着什么好的。

    换言之,好的。

    1
    foo();

    被有效地转化为好的。

    1
    foo.call(undefined);

    在javascript中,有像+-*这样的操作符。还有一个点运算符,它是.。好的。

    当与右边的函数和左边的对象一起使用时,.运算符有效地表示"将对象作为this传递给函数"。好的。

    例子好的。

    1
    2
    3
    4
    5
    6
    7
    8
    const bar = {
      name: 'bar',
      foo() {
        console.log(this);
      },
    };

    bar.foo();  // this is bar

    好的。

    换句话说,bar.foo()翻译成const temp = bar.foo; temp.call(bar);。好的。

    注意,函数是如何创建的并不重要(主要是…)。所有这些都会产生相同的结果好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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

    好的。

    再说一遍,这些都只是句法上的糖分好的。

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

    另一个褶皱是原型链。使用a.bjavascript时,首先查看a直接引用的对象,以获取b属性。如果在对象上没有找到b,那么javascript将在对象的原型中查找b。好的。

    定义对象原型有多种方法,2019年最常见的是class关键字。对于this而言,尽管这并不重要。重要的是,在对象a中,如果它在对象上发现了属性b,或者在它的原型链中发现了属性b,那么同样的规则也适用。函数b引用将使用call方法调用,并将a作为此答案顶部显示的对象传递。好的。

    现在。假设我们在调用另一个函数之前创建一个显式设置this的函数,然后用.操作符调用它。好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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,但我们明确地为object传递了另一个对象,因此当我们到达foo this时,这是内部对象。好的。

    这就是bind=>功能有效的作用。它们更像是句法上的糖分。它们有效地构建了一个新的不可见函数,与上面的bar完全相同,它在调用指定的任何函数之前显式地设置this。在绑定this的情况下,设置为您传递给bind的任何内容。好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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不存在,我们可以这样做。好的。

    1
    2
    3
    4
    5
    function bind(fn, objectForThis) {
      return function(...args) {
        return fn.call(objectForthis, ...args);
      };
    }

    然后我们可以这样称呼它好的。

    1
    2
    3
    4
    5
    function foo() {
      console.log(this);
    }

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

    arrow函数,=>运算符是bind的语法糖。好的。

    1
    const a = () => {console.log(this)};

    是一样的好的。

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

    就像bind一样,创建了一个新的不可见函数,用objectForThis的绑定值调用给定函数,但与bind不同,要绑定的对象是隐式的。当使用=>操作符时,它就是this所发生的一切。好的。

    所以,就像上面的规则一样好的。

    1
    const a = () => { console.log(this); }  // this is the global object
    1
    2
    'use strict';
    const a = () => { console.log(this); }  // this is undefined
    1
    2
    3
    4
    5
    6
    7
    8
    9
    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的新的不可见函数。b()将一如既往地发挥作用,如b.call(window)b.call(undefined)调用foo创建的新的无形功能。这个不可见的函数忽略了传入它的this,并将obj作为箭头函数的对象传递给它。好的。

    上面的代码翻译成好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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);

    1apply是与call相似的另一个功能。好的。

    1
    functionName.apply(objectForThis, arrayOfArgs);

    但是从概念上讲,从ES6开始,你甚至可以将其转化为好的。

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

    好啊。


    这种作用域的用法就像这样

    1
    2
    3
    4
    5
    6
    7
    8
    9
      <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)
    });

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


    javascript中的"this"关键字是什么

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

    换句话说,执行时的每个javascript函数都有一个对当前执行上下文的引用,称为this。执行上下文的意思是如何调用函数。

    要理解这个关键字,我们只需要知道如何、何时和从何处调用函数,而不需要知道如何和在何处声明或定义函数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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,这意味着它试图打印当前执行context(i.e.this object)的name属性值。

    在上面的代码片段中,当函数bike()被调用时,它会打印"ninja",因为没有指定执行上下文,所以默认情况下,它的全局上下文和全局上下文中存在一个变量名,其值为"ninja"。

    obj1().bike()调用的情况下,会打印"pulsar",其背后的原因是函数bike()被调用,执行上下文为obj1,所以this.name成为obj1.name。同obj2.bike()调用,函数bike()的执行上下文为obj2

    "this"的默认和隐式绑定

    如果我们处于严格模式,那么这个关键字的默认值是未定义的,否则这个关键字作为一个全局对象,它被称为这个关键字的默认绑定。(对于浏览器,默认为窗口对象)。

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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()是隐性结合的例子。在这里,bike函数被声明为obj1的一部分,但是不管我们在executeobj2.bike()时,执行的上下文是obj2,所以obj2.name被打印出来。

    知道如何、何时和从何处调用函数与在何处声明函数无关,这一点很重要。

    "this"关键字的显式和固定绑定

    如果我们使用带有调用函数的call和apply方法,那么这两个方法都将作为它们的第一个参数作为执行上下文。这就是这个绑定。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function bike() {
      console.log(this.name);
    }

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

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

    在上面的代码片段中,如果我们调用函数bike,其中call()方法传递执行上下文对象obj作为第一个参数,那么obj将被分配给这个对象,它将打印"pulsar",它只不过是obj.name而已。它被称为这个关键字的显式绑定。

    固定装订或硬装订

    我们可以强制这个对象保持不变,不管它是从哪里被调用的以及如何被调用的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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()bike.call(obj2)都调用了pulsar,这只不过是obj1.name的意思是函数bike的执行上下文始终是obj1和它的执行上下文,因为originalBikeFun.call(obj1);这种绑定只是显式绑定的另一种风格。称为固定绑定。


    总结thisjavascript:

    • EDOCX1的值(0)由函数的调用方式决定,而不是由函数的创建位置决定的!
    • 通常,EDOCX1的值(0)由点左边的对象确定。(全球空间中的window)
    • 在事件侦听器中,EDOCX1的值(0)是指调用事件的DOM元素。
    • 当使用new关键字调用in函数时,this的值指新创建的对象。
    • 可以通过函数:callapplybind来操纵this的值。

    例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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

    事件侦听器示例:

    1
    2
    3
    4
    5
    6
    7
    8
    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
    1
    2
    3
    4
    .foo:hover {
      color: red;
      cursor: pointer;
    }
    1
    click me

    示例构造函数:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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.


    简单回答:

    "this"关键字始终依赖于调用的上下文。它们在下面提到。

  • 用new关键字调用函数

    如果用new关键字调用函数,那么它将绑定到新创建的对象。

    1
    2
    3
    4
    5
    function Car(){
      this.name="BMW";
    }
    const myCar=new Car();
    myCar.name; // output"BMW"

    在上面,这将绑定到"mycar"对象

  • 使用调用和应用方法显式调用函数。

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

    1
    2
    3
    4
    5
    6
    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.
  • 如果用对象隐式调用函数,则此函数将绑定到该对象

    1
    2
    3
    4
    5
    6
    7
    8
    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)
  • 如果在没有任何上下文的情况下调用函数,则此函数将绑定到全局对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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
  • 在严格模式下,这将是未定义的

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