在Javascript中," this.something"查找范围链""?

时间:2015-09-25 23:28:46

标签: javascript oop scope javascript-objects

这就是我的意思。我正在练习面向对象的Javascript(我通过练习学习),为了好玩而创建了以下课程

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,它没有名为{的成员{1}}!所以我认为它抬高了范围链是正确的吗?这似乎与stack的整个想法相矛盾,但是......它的重点是什么?

3 个答案:

答案 0 :(得分:3)

简短的回答是“不”。执行上下文的 this 总是在当前执行上下文中解析,因此它与作用域无关。使用宽箭头函数,它设置为与外部执行上下文相同的值。

函数的 this 由函数的调用方式或 bind 设置决定。它不是词法设置(调用在代码中)或调用函数的地方。

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

fs.executeFunctions();

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

答案 1 :(得分:0)

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

  

this.stack = []; //< ---是Funstack

的任何实例的实例属性(成员)

使用“fs”(实例引用)调用“pushFunction”来引用

“this”(上下文)成为“fs”对象的任何内容..

如果仍不清楚,请尝试在javascript的“调用上下文”中阅读更多内容。

答案 2 :(得分:0)

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

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

请注意,您通过说:pushFunctionthis.pushFunction = function(f) { /* (...) */ }声明为该班级的成员。所以,你要在课堂上创建一个方法。这就是为什么this关键字引用作为该类实例的对象的原因。

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

  

TypeError:this.stack未定义

看一下下面的例子。



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'