"this"关键字如何运作?

Max*_*ich 1243 javascript this

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

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

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

Dan*_*ien 1305

我建议先阅读Mike West的文章Scope in JavaScript(mirror).它是thisJavaScript中概念和范围链的优秀,友好的介绍.

一旦你开始习惯this,规则实际上非常简单.所述的ECMAScript 5.1标准定义this:

§11.1.1this关键字

所述this关键字的计算结果为当前执行上下文的ThisBinding的值

ThisBinding是JavaScript解释器在评估JavaScript代码时维护的东西,比如一个特殊的CPU寄存器,它保存对象的引用.每当在三种不同情况之一中建立执行上下文时,解释器就会更新ThisBinding:

1.初始全局执行上下文

这是在顶层评估的JavaScript代码的情况,例如直接在<script>:

<script>
  alert("I'm evaluated in the initial global execution context!");

  setTimeout(function () {
      alert("I'm NOT evaluated in the initial global execution context.");
  }, 1);
</script>
Run Code Online (Sandbox Code Playgroud)

在初始全局执行上下文中评估代码时,ThisBinding设置为全局对象window(第10.4.1.1节).

输入eval代码

  • ...通过直接调用eval() ThisBinding保持不变; 它与调用执行上下文的ThisBinding(§10.4.2(2)(a))的值相同.

  • ...如果不是通过直接调用eval()
    ThisBinding ,则将其设置为全局对象,就像在初始全局执行上下文中执行一样(第10.4.2(1)节).

§15.1.2.1.1定义了直接调用的eval()内容.基本上,eval(...)是直接呼叫,而类似(0, eval)(...)var indirectEval = eval; indirectEval(...);间接呼叫eval().在JavaScript中查看chuckj(1,eval)('this')vs eval('this')的回答Dmitry Soshnikov的ECMA-262-5详细介绍.第2章严格模式.适用于何时使用间接eval()呼叫.

输入功能代码

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

在"大多数其他情况下"编写的原因是因为有八个ECMAScript 5内置函数允许在参数列表中指定ThisBinding.这些特殊函数采用所谓thisArg的函数,在调用函数时成为ThisBinding(第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在执行上下文中调用给定,其中ThisBinding设置为thisArgif;如果提供的话; 否则,到全局对象.

这些是纯JavaScript的规则.当您开始使用JavaScript库(例如jQuery)时,您可能会发现某些库函数会操纵它的值this.这些JavaScript库的开发人员这样做是因为它倾向于支持最常见的用例,并且库的用户通常会发现这种行为更方便.当传递引用this库函数的回调函数时,您应该参考文档以获得有关this函数调用时的值的任何保证.

如果您想知道JavaScript库如何操纵它的值this,那么库只是使用一个接受a的内置JavaScript函数thisArg.您也可以使用回调函数编写自己的函数,并且thisArg:

function doWork(callbackfn, thisArg) {
    //...
    if (callbackfn != null) callbackfn.call(thisArg);
}
Run Code Online (Sandbox Code Playgroud)

我还没有提到一个特例.当通过构造一个新的对象new操作时,JavaScript解释器创建一个新的空对象,设置一些内部属性,然后调用新对象的构造函数.因此,当一个函数被调用在构造方面,的值this是解释创建的新对象:

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);
Run Code Online (Sandbox Code Playgroud)

箭头功能

箭头功能(在ECMA6中引入)改变了范围this.请参阅现有的规范问题,箭头函数与函数声明/表达式:它们是等效/可交换的吗?欲获得更多信息.但简而言之:

箭头函数没有自己的this....绑定.相反,这些标识符在词法范围内像任何其他变量一样被解析.这意味着在箭头函数内部,this... this指定环境中的箭头函数定义的值.

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

要显示答案,请将鼠标悬停在浅黄色框上.

  1. this标记线的价值是多少?为什么?

    window - 标记的行在初始全局执行上下文中进行评估.

    if (true) {
        // What is `this` here?
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 执行this时标记线的值obj.staticFunction()是多少?为什么?

    obj - 在对象上调用函数时,ThisBinding设置为该对象.

    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);
      
    Run Code Online (Sandbox Code Playgroud)

  3. this标记线的价值是多少?为什么?

    window

    在此示例中,JavaScript解释器输入功能代码,但由于未在对象上调用myFun/ obj.myMethod,因此将ThisBinding设置为window.

    这与Python不同,在Python中访问method(obj.myMethod)会创建绑定方法对象.

    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);
      
    Run Code Online (Sandbox Code Playgroud)

  4. this标记线的价值是多少?为什么?

    window

    这个很棘手.在评估eval代码时,thisobj.但是,在eval代码中,myFun不会在对象上调用,因此将ThisBinding设置window为调用.

    function myFun() {
        return this; // What is `this` here?
    }
    var obj = {
        myMethod: function () {
            eval("myFun()");
        }
    };
    
    Run Code Online (Sandbox Code Playgroud)
  5. this标记线的价值是多少?为什么?

    obj

    该行myFun.call(obj);正在调用特殊的内置函数Function.prototype.call(),该函数接受thisArg作为第一个参数.

    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);
      
    Run Code Online (Sandbox Code Playgroud)

  • @Ali:它们是对ECMAScript标准版本5.1 [ECMA-262](http://www.ecma-international.org/publications/standards/Ecma-262.htm)中各节的引用.我提供它们,以便您可以根据需要阅读标准技术细节. (6认同)
  • 来自 Python 的人会想象当我遇到第三个例子时我的沮丧程度.. smh (3认同)
  • 但是,http://jsfiddle.net/H4LYm/2/显示`setTimeout`示例有一个`this`of`window(global)`. (2认同)
  • 另一种常见情况:通过将“this”设置为事件的“currentTarget”来调用事件处理程序。将来可以包含这三个提案:[绑定运算符 `::`](//github.com/tc39/proposal-bind-this)、[显式此](//github.com/gilbert/es-explicit -this), [`this` 参数反射](//github.com/hax/proposal-function-this)。像“onclick”这样的 DOM 0 事件属性也值得注意:JS 代码隐式包装在“document”的一个“with”作用域中,以及一个用于单击元素的“with”作用域中,[导致混乱](/a/43459991/4642212);`this` 是具有该属性的元素。 (2认同)
  • @LRDPRDX 嗯,这个答案包含了“this”的每一个细节。但没有人真正在全局范围内需要 `this`,`with` 已被弃用,`eval` 不鼓励,严格模式应该在任何地方使用,等等。剩下的就是 `obj.method()` 用 `调用 `method`。如果“method”是“function”或方法,则 obj` 为“this”;`func()` 调用 `func` 时不带任何 `this`;`.bind`、`.call` 和 `.apply` 可用于显式绑定 `this`;箭头函数没有“this”绑定。类:在静态事物中,“this”指的是类本身,在非静态事物中指的是正在创建的实例。就是这样。 (2认同)

Mah*_*aha 149

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

1.在全球范围内使用时

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

document.write(this);  //[object Window]
Run Code Online (Sandbox Code Playgroud)

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

function f1()
{
   return this;
}
document.write(f1());  //[object Window]
Run Code Online (Sandbox Code Playgroud)

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

function f()
{
    return this;
}

document.write(window.f()); //[object Window]
Run Code Online (Sandbox Code Playgroud)

2.在对象内部使用时

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

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

我在上面用双引号括起来.它的目的是指出,如果将对象嵌套在另一个对象中,则this绑定到直接父对象.

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

document.write(obj.nestedobj.f()); //[object Object]:nestedobj
Run Code Online (Sandbox Code Playgroud)

即使您将函数显式添加到对象作为方法,它仍然遵循上述规则,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
Run Code Online (Sandbox Code Playgroud)

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 
Run Code Online (Sandbox Code Playgroud)

尝试所有功能

我们也可以尝试以上功能.但是有一些差异.

  • 上面我们使用对象文字表示法向对象添加了成员​​.我们可以使用添加成员到函数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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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   
Run Code Online (Sandbox Code Playgroud)

6.内部调用(),apply()和bind()函数

  • 所有这些方法都是定义的Function.prototype.
  • 这些方法允许编写一次函数并在不同的上下文中调用它.换句话说,它们允许指定在this执行函数时将使用的值.它们还会在调用时将任何参数传递给原始函数.
  • fun.apply(obj1 [, argsArray])设置obj1thisinside 的值fun()并调用fun()传递元素argsArray作为其参数.
  • fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])- 设置obj1thisinside 的值,fun()并将调用作为参数fun()传递arg1, arg2, arg3, ....
  • fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])- 返回对函数的引用,其中fun包含this内部fun绑定obj1fun绑定到指定参数的参数arg1, arg2, arg3,....
  • 现在的区别apply,call并且bind必须变得明显.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>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)


use*_*110 61

JavaScript的 this

简单的函数调用

考虑以下功能:

function foo() {
    console.log("bar");
    console.log(this);
}
foo(); // calling the function
Run Code Online (Sandbox Code Playgroud)

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

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

如果在node.js之类的环境中运行同一段代码,this则会引用应用程序中的全局变量.

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

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

在对象上调用函数

有不同的方法来做到这一点.如果有一个名为Javascript中就像调用本地方法forEachslice,你应该已经知道,this在这种情况下,变量是指Object在其上被称为该函数(请注意,在JavaScript中,刚才的一切是Object,包括ArrayS和FunctionS).以下面的代码为例.

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

如果a Object包含一个包含a的属性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
Run Code Online (Sandbox Code Playgroud)

考虑更常见的实际情况:

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
Run Code Online (Sandbox Code Playgroud)

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`
Run Code Online (Sandbox Code Playgroud)

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

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

挺直的,嗯?

请注意,官方的ECMAScript spec no no声明这类函数是实际constructor函数.它们只是普通的功能,new可以用于任何功能.只是我们这样使用它们,所以我们只将它们称为它们.

在函数上调用函数:callapply

所以是的,既然functions也是Objects(实际上是Javascript中的第一类变量),甚至函数都有方法......好吧,函数是自己的.

所有函数都从全局继承,其中有Function两个方法是callapply,并且都可以用来操作this它们被调用的函数的值.

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

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

apply几乎与call接受相同,它只需要两个参数:thisArg和一个包含要传递给函数的参数的数组.所以上面的call调用可以翻译成apply这样:

foo.apply(thisArg, [1,2,3])
Run Code Online (Sandbox Code Playgroud)

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

介绍.... bind!

bind是的哥callapply.它也是FunctionJavascript中全局构造函数的所有函数继承的方法.之间的差异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]`
Run Code Online (Sandbox Code Playgroud)

看到三者之间的区别?它很微妙,但它们的使用方式不同.喜欢callapply,bindthis将通过点方法调用覆盖set 的值.

另请注意,这三个函数都不会对原始函数进行任何更改.call并将apply从新构造的函数返回值,同时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"
        });
    }
  };
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,我们看到this使用嵌套范围更改的值,但我们想要this原始范围的值.因此,我们"复制" thisthat和使用的副本,而不是this.聪明,是吗?

指数:

  1. 什么是this默认保留?
  2. 如果我们将该函数称为具有Object-dot表示法的方法,该怎么办?
  3. 如果我们使用new关键字怎么办?
  4. 我们如何处理thiscallapply
  5. bind.
  6. 复制this以解决嵌套范围问题.


aru*_*ngh 48

"这个"就是范围.每个函数都有自己的作用域,因为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);

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

  • `this`关键字与范围无关.此外,它还具有不属于对象属性的函数的含义. (11认同)
  • `this`不是关于范围的全部.它是关于执行上下文的所有内容,它与范围不同.JavaScript是词法范围的(意味着范围由代码的位置决定),但是`this`取决于如何调用包含它的函数 - 而不是函数的位置. (7认同)
  • "JS中的所有东西都是一个对象"并非如此,JavaScript也有原始价值,请参阅http://bclary.com/2004/11/07/#a-4.3.2 (6认同)
  • 原始值似乎有自己的一些方法,比如String #substring(),Number#toString()等.所以,也许没有与那篇文章相同的命名法,它们的行为就像它们是对象一样(它们是所有原型,即String #substring()实际上是:String.prototype.substring = function(){...}).如果我错了,请纠正我. (6认同)

Sep*_*eph 17

this在Javascript中始终引用正在执行的函数的"所有者" .

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

所以,如果我这样做

function someKindOfFunction() {
   this.style = 'foo';
}
Run Code Online (Sandbox Code Playgroud)

element.onclick = someKindOfFunction;

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

<element onclick="someKindOfFunction()">

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


car*_*rso 16

由于这个帖子已经出现了问题,我已经为新this主题的读者编写了几点.

价值如何this确定?

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

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

this 在对象调用定义它的函数之前,不会为其赋值.在全局范围中,所有全局变量和函数都在window对象上定义.因此,this在全局函数中指的是(并且具有值)全局window对象.

如果use strict,this在全球和在未绑定到任何物体匿名函数持有的价值undefined.

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

表

什么是未来

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!
Run Code Online (Sandbox Code Playgroud)

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


参考文献:

  1. 这个和对象原型,由凯尔辛普森.©2014 Getify Solutions.
  2. javascriptissexy.com - http://goo.gl/pvl0GX
  3. Angus Croll - http://goo.gl/Z2RacU


blo*_*ead 13

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

  1. 如何调用函数(包括作为对象方法,使用callapply,使用new)
  2. 使用bind
  3. 词法的箭头功能(他们采用这个他们外执行上下文)

无论该范围上下文是什么,都由"this"引用.

您可以更改设置的值这个 范围 情况下使用func.call,func.applyfunc.bind.

默认情况下,什么迷惑大多数初学者,当回调的事件是一个DOM元素上引发之后监听器被调用时,作用域上下文 这个函数的值是的DOM元素.

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

  • 说每个函数*call*都有一个范围,这是更正确的.换句话说,Javascript中对"this"的混淆是它不是**函数本身的内在属性,而是函数调用方式的工件. (9认同)
  • `this`确实*不*引用函数的作用域.`this`将引用一个特定的对象(或者可能是`undefined`),正如你所说的那样可以用`.call()`或`.apply()`来改变.函数的*作用域*(基本上,当简化时)它可以访问哪些变量,这完全取决于声明函数的位置并且不能更改. (2认同)

zan*_*ngw 10

这里是一个很好的来源thisJavaScript.

以下是摘要:

  • 全球这个

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

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

    node使用repl时,this是顶级命名空间.你可以称之为global.

    >this
      { ArrayBuffer: [Function: ArrayBuffer],
        Int8Array: { [Function: Int8Array] BYTES_PER_ELEMENT: 1 },
        Uint8Array: { [Function: Uint8Array] BYTES_PER_ELEMENT: 1 },
        ...
    >global === this
     true
    
    Run Code Online (Sandbox Code Playgroud)

    node从脚本执行this时,全局范围作为空对象开始.它不一样global

    \\test.js
    console.log(this);  \\ {}
    console.log(this === global); \\ fasle
    
    Run Code Online (Sandbox Code Playgroud)
  • 这个功能

除了DOM事件处理程序或thisArg提供a的情况(参见下文),在节点和浏览器中使用this未调用的函数都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>
Run Code Online (Sandbox Code Playgroud)

如果你使用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>
Run Code Online (Sandbox Code Playgroud)

如果你调用一个函数newthis将是一个新的环境,也不会引用全局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>
Run Code Online (Sandbox Code Playgroud)
  • 原型这个

您创建的函数将成为函数对象.它们会自动获取一个特殊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"
Run Code Online (Sandbox Code Playgroud)

分配数组对象通常是错误的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 []
Run Code Online (Sandbox Code Playgroud)
  • 反对这个

您可以this在对象的任何函数中使用它来引用该对象上的其他属性.这与使用创建的实例不同new.

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

obj.logFoo(); //logs "bar"
Run Code Online (Sandbox Code Playgroud)
  • DOM事件这个

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

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();
Run Code Online (Sandbox Code Playgroud)

除非你bind的背景

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();
Run Code Online (Sandbox Code Playgroud)
  • HTML这个

您可以在其中放置JavaScript的HTML内部属性this是对元素的引用.

<div id="foo" onclick="console.log(this);"></div>
<script type="text/javascript">
document.getElementById("foo").click(); //logs <div id="foo"...
</script>
Run Code Online (Sandbox Code Playgroud)
  • 评估这个

您可以使用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();
Run Code Online (Sandbox Code Playgroud)
  • 有了这个

您可以使用with添加this到当前作用域来读取和写入值this而无需this显式引用.

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"
Run Code Online (Sandbox Code Playgroud)
  • jQuery这个

jQuery在很多地方都会this引用一个DOM元素.

<div class="foo bar1"></div>
<div class="foo bar2"></div>
<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();
});
</script>
Run Code Online (Sandbox Code Playgroud)


Arm*_*ian 9

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

用两个词来说,this在JavaScript中指向运行当前函数的对象(或从其执行上下文)并且它始终是只读的对象,无论如何都无法设置它(这样的尝试最终将会出现'无效左手'一边分配'消息.

对于事件处理程序:内联事件处理程序,例如<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)">


Dmi*_*tin 9

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

在JavaScript中对'this'关键字的温和解释

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


遇到麻烦时this,不要问自己:

从何this而来

不要问自己:

如何调用该函数?

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

this箭头函数定义的值是多少?

这种心态在处理时是正确的,this并且可以帮助您避免头痛.


Aru*_*ore 9

关于如何在JavaScript中解释"this"关键字存在很多困惑.希望这篇文章能够让所有人一劳永逸地休息.还有更多.请仔细阅读整篇文章.预先警告这篇文章很长.

无论使用它的上下文,"this"总是引用Javascript中的"当前对象".但是,"当前对象"根据上下文而不同.所述上下文可以是恰好1 6的以下内容:

  1. 全局(即所有功能之外)
  2. 内部直接"非绑定函数"调用(即通过调用functionName.bind绑定的函数)
  3. 内部间接"非约束函数"通过functionName.callfunctionName.apply调用
  4. 在"绑定函数"调用内部(即通过调用functionName.bind绑定函数)
  5. 通过"新"创建对象
  6. 内联DOM事件处理程序

以下逐一描述每个上下文:

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

    在所有函数之外(即在全局上下文中),"当前对象"(以及因此"this"的值)始终是浏览器的 "窗口"对象.

  2. 内部直接"非约束函数"调用:

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

    function UserDefinedFunction(){
        alert(this)
        }
    
    Run Code Online (Sandbox Code Playgroud)

    它成为窗口对象的属性,就好像您已将其定义为

    window.UserDefinedFunction=function(){
      alert(this)
    }  
    
    Run Code Online (Sandbox Code Playgroud)

    在"非严格模式"中,直接通过"UserDefinedFunction()"调用/调用此函数 将自动调用/调用它作为"window.UserDefinedFunction()"使"窗口"作为 "当前对象"(因此值"这个")在"UserDefinedFunction"中.在"非严格模式"中调用此函数将导致以下结果

    UserDefinedFunction() // displays [object Window]  as it automatically gets invoked as window.UserDefinedFunction()
    
    Run Code Online (Sandbox Code Playgroud)

    在"严格模式"中,通过"UserDefinedFunction()"直接调用/调用该函数 将"NOT"自动调用/调用它作为"window.UserDefinedFunction()".具有"当前对象"(以及"this"的值)) "UserDefinedFunction"中的内容应该是未定义的.在"严格模式"中调用此功能将导致以下结果

    UserDefinedFunction() // displays undefined
    
    Run Code Online (Sandbox Code Playgroud)

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

    window.UserDefinedFunction() // "always displays [object Window]   irrespective of mode."
    
    Run Code Online (Sandbox Code Playgroud)

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

     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
    
    Run Code Online (Sandbox Code Playgroud)

    在上面的例子中,我们看到当通过o1调用"UserDefinedFunction"时,"this"取值为o1,并显示其属性"a""b"的值.的值"C""d"被示出为未定义O1没有定义这些属性

    类似地,当"UserDefinedFunction"是通过调用O2, "这"取的值O2和其属性的值"C""d"获得的displayed.The值的"a""b"的被示出为未定义o2的确实没有定义这些属性.

  3. 内部间接"非约束函数"通过functionName.callfunctionName.apply调用:

    当通过functionName.callfunctionName.apply调用 "非绑定函数"时,"当前对象"(以及因此"this"的值)被设置为传递给调用"this"参数(第一个参数)的值 /申请.以下代码演示了相同的内容.

    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
    
    Run Code Online (Sandbox Code Playgroud)

    上面的代码清楚地表明,任何"NON Bound Function"的"this"值都可以通过call/apply来改变.此外,如果未将 "this"参数显式传递给call/apply,则"当前对象"(因此"this"的值)在非严格模式下设置为"window",在严格模式下设置为"undefined".

  4. 在"绑定函数"调用内部(即通过调用functionName.bind绑定的函数):

    绑定函数是其"this"值已修复的函数.以下代码演示了绑定函数时"this"的工作原理

    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
    
    Run Code Online (Sandbox Code Playgroud)

    如上面的代码所示,任何"绑定函数"的"this"值都不能通过call/apply来改变.此外,如果未将"this" 参数显式传递给bind,则"当前对象" (因此"this"的值)在非严格模式下设置为"window",在严格模式下设置为"undefined".还有一件事.绑定已绑定的函数不会更改"this"的值.它仍然设置为第一个绑定函数设置的值.

  5. 通过"新"创建对象:

    在构造函数内部,"当前对象"(以及"this"的值 )引用当前通过"new"创建的对象,而不管函数的绑定状态如何.但是,如果构造函数是绑定函数,则应使用为绑定函数设置的预定义参数集调用它.

  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>
    
    Run Code Online (Sandbox Code Playgroud)

    上述示例中的"this"分别表示"button"元素和"div"元素.

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

    在单击"div"元素的第二个示例中,它将调用OnDivClick函数,其第二个参数引用单击的div元素.但是, OnDivClick 中"this"的值不会引用单击的div 元素.它应分别在Non strictStrict Modes中设置为"window object""undefined"(如果OnDivClick未绑定的函数)或设置为预定义的Bound值(如果OnDivClick绑定函数)

以下总结了整篇文章

  1. 在全局上下文中,"this"总是指"窗口"对象

  2. 无论何时调用函数,都会在对象("当前对象")的上下文中调用它.如果当前对象没有明确规定,在当前的对象"窗口对象"非严格模式"不确定"默认情况下在严格模式.

  3. 非绑定函数中"this"的值是在调用函数的上下文中对对象的引用("当前对象")

  4. 非绑定函数中"this"的值可以通过调用应用函数的方法来覆盖 .

  5. "this"的值对于Bound函数是固定的,并且不能通过调用应用函数的方法来覆盖.

  6. 绑定和已绑定的函数不会更改"this"的值.它仍然设置为第一个绑定函数设置的值.

  7. 构造函数中"this"的值是正在创建和初始化的对象

  8. 内联DOM事件处理程序中"this"的值是对给定事件处理程序的元素的引用.


Jam*_*ard 7

这是我见过的最好的解释. 了解JavaScript的这种清晰

引用总是指(并保持的值)的物体的单一对象,而且它通常是一个函数或方法内使用,虽然它可以在函数外,在全球范围内使用.请注意,当我们使用严格模式时,它在全局函数和未绑定到任何对象的匿名函数中保存undefined的值.

有四个条件,其中可能会造成混淆:

  1. 当我们传递一个方法(使用)作为一个参数用作回调函数.
  2. 另一个被误解的例子是我们使用内部方法(闭包).重要的是要注意闭包不能通过使用this关键字访问外部函数的this变量,因为this变量只能由函数本身访问,而不能由内部函数访问.
  3. 将方法分配给变量时使用此选项.在这个值被绑定到另一个对象,如果我们分配使用该给一个变量的方法
  4. 使用使用绑定时,应用和调用方法.

他给出了我认为非常有用的代码示例,解释和代码修复.


tat*_*ata 6

如果你不完全理解JS,很难掌握JS,或者写出更多的东西.你不能只是快速下降:)我认为开始使用JS的最佳方式是首先观看道格拉斯·克罗克福德的这些视频讲座 - http://yuiblog.com/crockford/,它涵盖了这一点和那个,以及关于JS的一切.

  • 链接已经死了. (3认同)
  • 哈,现在Crockford不喜欢*this*和程序而不使用它.;-) (2认同)

小智 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;
Run Code Online (Sandbox Code Playgroud)


Nip*_*una 5

this是JavaScript中一个被误解的概念之一,因为它的行为因地而异。简单来说,this是指我们当前正在执行的函数“所有者”

this帮助获取我们正在使用的当前对象(又名执行上下文)。如果你了解这是越来越当前执行的函数对象,你可以很容易地了解当前thisIS

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
Run Code Online (Sandbox Code Playgroud)

在上方,我们创建了3个具有相同名称“ val”的变量。一个在全局上下文中,一个在obj内部,另一个在obj的innerMethod内部。JavaScript通过将范围链从本地扩展到全局来解析特定上下文中的标识符。


很少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
Run Code Online (Sandbox Code Playgroud)

当执行line1时,JavaScript将为函数调用建立执行上下文(EC),设置this最后一个“”之前的内容所引用对象。。因此,在最后一行中,您可以了解它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
Run Code Online (Sandbox Code Playgroud)

Person()执行new时,将创建一个全新的对象。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 
Run Code Online (Sandbox Code Playgroud)

如果我们错过了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>
Run Code Online (Sandbox Code Playgroud)

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



小智 5

“ this”的值取决于在其中执行功能的“上下文”。上下文可以是任何对象或全局对象,即窗口。

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

在两种情况下,都将其设置为window。


归档时间:

查看次数:

390124 次

最近记录:

6 年 前