嵌套函数中的Javascript"this"指针

JoJ*_*Dad 82 javascript nested function this

我有一个关于如何在嵌套函数场景中处理"this"指针的问题.

假设我将以下示例代码插入到网页中.当我调用嵌套函数"doSomeEffects()"时出错.我检查了Firebug,它表明当我在嵌套函数中时,"this"指针实际上指向全局"窗口"对象 - 我没想到.我一定不能理解正确的东西,因为我认为既然我在对象的函数中声明了嵌套函数,它应该具有与函数相关的"局部"范围(即"this"指针将指向对象本身就像它是如何在我的第一个"如果"声明中.

任何指针(没有双关语意)将不胜感激.

var std_obj = {
  options : { rows: 0, cols: 0 },
  activeEffect : "none",
  displayMe : function() {

    // the 'this' pointer is referring to the std_obj
    if (this.activeEffect=="fade") { }

    var doSomeEffects = function() {

      // the 'this' pointer is referring to the window obj, why?
      if (this.activeEffect=="fade") { }

    }

    doSomeEffects();   
  }
};

std_obj.displayMe();
Run Code Online (Sandbox Code Playgroud)

Kyl*_*vis 112

在JavaScript中,this对象实际上是基于如何进行函数调用.

通常,有三种方法可以设置this对象:

  1. someThing.someFunction(arg1, arg2, argN)
  2. someFunction.call(someThing, arg1, arg2, argN)
  3. someFunction.apply(someThing, [arg1, arg2, argN])

在所有上述示例中,this对象将是someThing.调用没有前导父对象的函数通常会获得全局对象,在大多数浏览器中这意味着window对象.


chu*_*ckj 32

this不是闭包范围的一部分,它可以被认为是在调用站点绑定的函数的附加参数.如果该方法未作为方法调用,则将全局对象作为传递this.在浏览器中,全局对象与之相同window.例如,考虑以下功能,

function someFunction() {
}
Run Code Online (Sandbox Code Playgroud)

和以下对象,

var obj = { someFunction: someFunction };
Run Code Online (Sandbox Code Playgroud)

如果使用方法语法调用函数,例如,

obj.someFunciton();
Run Code Online (Sandbox Code Playgroud)

然后this必然会obj.

如果你直接调用someFunction(),比如

someFunction();
Run Code Online (Sandbox Code Playgroud)

然后this绑定到全局对象,即window.

最常见的工作是将其捕获到闭包中,例如:

displayMe : function() {      

    // the 'this' pointer is referring to the std_obj      
    if (this.activeEffect=="fade") { }      
    var that = this;  
    var doSomeEffects = function() {      

      // the 'this' pointer is referring to global
      // that, however, refers to the outscope this
      if (that.activeEffect=="fade") { }      
    }      

    doSomeEffects();         
 }      
Run Code Online (Sandbox Code Playgroud)


小智 30

由于这似乎是同类中最受欢迎的问题之一,所以这些年来,让我使用箭头函数添加ES6解决方案:

var std_obj = {
  ...
  displayMe() {
    ...
    var doSomeEffects = () => {
                        ^^^^^^^    ARROW FUNCTION    
      // In an arrow function, the 'this' pointer is interpreted lexically,
      // so it will refer to the object as desired.
      if (this.activeEffect=="fade") { }
    };
    ...    
  }
};
Run Code Online (Sandbox Code Playgroud)

  • 现在*那是*进步! (5认同)

Sha*_*ane 10

机箱变量与"this"之间存在差异."this"实际上是由函数的调用者定义的,而显式变量在称为机箱的函数声明块中保持不变.请参阅以下示例:

function myFirstObject(){
    var _this = this;
    this.name = "myFirstObject";
    this.getName = function(){
       console.log("_this.name = " + _this.name + " this.name = " + this.name);  
    }
}

function mySecondObject(){
    var _this = this;
    this.name = "mySecondObject";
    var firstObject = new myFirstObject();
    this.getName = firstObject.getName
}

var secondObject = new mySecondObject();
secondObject.getName();
Run Code Online (Sandbox Code Playgroud)

你可以在这里试试:http: //jsfiddle.net/kSTBy/

您的函数中发生的是"doSomeEffects()",正在显式调用,这意味着上下文或函数的"this"是窗口.如果"doSomeEffects"是原型方法,例如this.doSomeEffects on say"myObject",那么myObject.doSomeEffects()会导致"this"成为"myObject".

  • 对于懒惰和不耐烦,这个演示记录:`_this.name = myFirstObject this.name = mySecondObject` (4认同)

ron*_*725 7

要了解此问题,请尝试获取以下代码段的输出

var myObject = {
    foo: "bar",
    func: function() {
        var self = this;
        console.log("outer func:  this.foo = " + this.foo);
        console.log("outer func:  self.foo = " + self.foo);
        (function() {
            console.log("inner func:  this.foo = " + this.foo);
            console.log("inner func:  self.foo = " + self.foo);
        }());
    }
};
myObject.func();
Run Code Online (Sandbox Code Playgroud)

上面的代码将以下内容输出到控制台:

outer func:  this.foo = bar
outer func:  self.foo = bar
inner func:  this.foo = undefined
inner func:  self.foo = bar
Run Code Online (Sandbox Code Playgroud)

在外部函数中,this和self都引用myObject,因此两者都可以正确引用和访问foo.

但是,在内部函数中,这不再引用myObject.因此,this.foo在内部函数中是未定义的,而对局部变量self的引用仍然在范围内并且可以在那里访问.(在ECMA 5之前,内部函数中的这个将引用全局窗口对象;而从ECMA 5开始,内部函数中的这个将是未定义的.)

  • 为什么会这样呢? (2认同)