在 Javascript 中,"this.something" 是否查找 "something" 的作用域链?

In Javascript, does "this.something" look up the scope chain for "something"?

这就是我的意思。我正在练习我的面向对象 Javascript(我从实践中学习),创建了以下内容 class 为了好玩

function Funcstack ( ) 
{
      this.stack = []; // stack/array of functions w/ no params

      this.pushFunction = function ( f ) 
      {
         // f: function w/ no params
         this.stack.push(f);
      }

      this.popFunction = function ( f )
      {
        // f: function w/ no params   
          var n = this.stack.length;
          if (n > 0) this.stack.splice(n - 1, 1);
      }
      this.executeFunctions = function ( ) 
      {
          // execute functions from top to bottom of stack
          for ( var i = (this.stack.length - 1); i >= 0; --i )
          {
             var thisfunc = this.stack[i];    
             thisfunc();
          }
      }
}

var fs = new Funcstack();
fs.pushFunction(function() { console.log('z'); });
fs.pushFunction(function() { console.log('y'); });
fs.pushFunction(function() { console.log('x'); });
fs.executeFunctions(); // should print 'xyz'

并对它的工作感到惊讶。主要原因是因为我认为,例如,在

      this.pushFunction = function ( f ) 
      {
         // f: function w/ no params
         this.stack.push(f);
      }

函数体无法识别 this.stack,因为 this 在特定上下文中指的是调用函数 pushFunction,它没有名为 [=18] 的成员=]!那么我认为它查找了作用域链是否正确?这似乎与 this 的整个想法相矛盾,但是......它有什么意义?

它起作用的原因是调用上下文。

this.stack = []; // <--- is an instance property ( member ) of any instance of Funstack

当您调用 "pushFunction" 使用 "fs"(实例引用)来引用

"this"(上下文)变成任何 "fs" 对象是..

如果仍然不清楚,请尝试阅读更多关于 javascript 的 "calling context"。

简短的回答是 "No"。执行上下文的 this 总是在当前执行上下文中解析,因此它与范围无关。对于宽箭头函数,它被设置为与外部执行上下文相同的值。

函数的 this 由调用函数的方式或通过 bind 设置来设置。它不是按词法设置的(调用在代码中的位置)或调用函数的位置。

其中 this 是一个对象(总是在非严格模式下)然后它的属性被解析的方式与解析任何对象的属性的方式相同,首先是它自己,然后是它的[[Prototype]]链。将函数作为对象的方法调用的地方:

fs.executeFunctions();

然后 基础对象 (fs) 在函数内被设置为 this。因此,当解析 this.stack.length 时,this 引用 fs 实例并且 executeFunctions 被解析为 fs.

的 属性

当您说:var fs = new Funcstack(); 时,您声明的对象是 class Funcstack 的一个实例。请注意,在 constructor 中,您正在声明它的一些属性和方法。

因此,所有这些方法中的关键字 this 将引用您创建的对象。如果需要,您可以随时使用 call, apply or bind 更改上下文。

请注意,您是在声明 pushFunction 为 class 的成员,方法是:this.pushFunction = function(f) { /* (...) */ }。因此,您正在为 class 创建一个方法。这就是为什么 this 关键字引用作为 class.

实例的对象的原因

如果您将函数声明为 var pushf = function(f) { /* (...) */ },然后在 class Funcstack 的某个方法中调用该函数,您将得到错误:

TypeError: this.stack is undefined

看看下面的例子。

function Funcstack() {
  this.stack = []; // stack/array of functions w/ no params

  var pushf = function _pushFunction(f) {
    this.stack.push(f);
  }

  this.pushFunction = function(f) {
    // f: function w/ no params
    pushf(f);
  }

  this.popFunction = function(f) {
    // f: function w/ no params   
    var n = this.stack.length;
    if (n > 0) this.stack.splice(n - 1, 1);
  }
  this.executeFunctions = function() {
    // execute functions from top to bottom of stack
    for (var i = (this.stack.length - 1); i >= 0; --i) {
      var thisfunc = this.stack[i];
      thisfunc();
    }
  }
}

var fs = new Funcstack();
fs.pushFunction(function() {
  console.log('z');
});
fs.pushFunction(function() {
  console.log('y');
});
fs.pushFunction(function() {
  console.log('x');
});
fs.executeFunctions(); // should print 'xyz'