简体   繁体   English

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

[英]In Javascript, does “this.something” look up the scope chain for “something”?

Here's what I mean. 这就是我的意思。 I'm practicing my object-oriented Javascript (I learn by practice), created the following class for fun 我正在练习我的面向对象的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'

and was surprised that it worked. 并对它的工作感到惊讶。 The main reason is because I thought that, for example, in 主要原因是因为我认为例如

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

the body of the function wouldn't recognize this.stack because this in the particular context refers to the invoking function pushFunction which doesn't have a member named stack ! 该函数体不会承认this.stack ,因为this在特定情况下是指调用函数pushFunction不有一个成员叫stack So am I correct in thinking that it looked up the scope chain? 因此,我认为它查找范围链是否正确? That seems to contradict the whole idea of this , though ... What's the point of it? 这似乎矛盾的整体思路this ,虽然...什么的地步了吗?

The short answer is "No". 最简洁的答案是不”。 An execution context's this is always resolved in the current execution context, therefore it has nothing to do with scope. 执行上下文的问题总是在当前执行上下文中解决,因此它与作用域无关。 With broad arrow functions, it's set to the same value as the outer execution context. 使用宽箭头功能,将其设置为与外部执行上下文相同的值。

A function's this is set by how the function is called or by setting with bind . 通过调用函数的方式或通过bind来设置函数的this It's not set lexically (where the call is in the code) or where the function is called from. 它不是按词法设置的(代码中的调用位置),也不是从中调用函数的位置。

Where this is an object (always in non–strict mode) then its properties are resolved in the same way any object's properties are resolved, firstly on itself, then on its [[Prototype]] chain. 如果是一个对象(始终处于非严格模式),则其解析属性的方式与解析任何对象的属性的方式相同,首先是解析其本身,然后解析其[[Prototype]]链。 Where a function is called as a method of an object: 将函数称为对象的方法的地方:

fs.executeFunctions();

then the base object (fs) is set to this within the function. 然后在函数中将基础对象 (fs)设置为此 Therefore, when this.stack.length is resolved, this references the fs instance and executeFunctions is resolved as a property of fs . 因此,当this.stack.length被解析时, 引用fs实例, executeFunctions被解析为fs的属性。

The reason it works is because of the calling context. 它起作用的原因是由于调用上下文。

this.stack = []; this.stack = []; // <--- is an instance property ( member ) of any instance of Funstack // <---是Funstack的任何实例的实例属性(成员)

When you invoke "pushFunction" using "fs" ( the instance reference ) to reference 当您使用“ fs”(实例引用)调用“ pushFunction”来引用时

"this" ( the context ) becomes whatever "fs" object is.. “ this”(上下文)变成任何“ fs”对象。

If it still unclear, try reading more on javascript's "calling context". 如果仍不清楚,请尝试阅读有关javascript的“调用上下文”的更多信息。

When you say: var fs = new Funcstack(); 当您说: var fs = new Funcstack(); , you're declaring an object that is an instance of the class Funcstack . ,您声明的对象是Funcstack类的实例。 Note that inside the constructor , you are declaring some properties and methods of it. 请注意,在constructor内部,您要声明其一些属性和方法。

So, the keyword this in all those methods will refer to the object you've created. 因此,所有这些方法中的关键字this都将指向您创建的对象。 You can change the context by using call , apply or bind if you want, at anytime. 您可以随时通过使用callapplybind来更改上下文。

Note that you are declaring the pushFunction as a member of the class by saying: this.pushFunction = function(f) { /* (...) */ } . 请注意,您通过这样声明将pushFunction声明为类的成员: this.pushFunction = function(f) { /* (...) */ } So, you're creating a method into the class. 因此,您要在类中创建一个方法。 That's why the this keyword refers to the object that is an instance of that class. 这就是为什么this关键字引用作为该类实例的对象的原因。

If you declared the function as var pushf = function(f) { /* (...) */ } , and then called that function inside some method of the class Funcstack , you would get the error: 如果将函数声明为var pushf = function(f) { /* (...) */ } ,然后在Funcstack类的某些方法中调用该函数,则会出现错误:

TypeError: this.stack is undefined TypeError:this.stack未定义

Take a look at the example below. 看下面的例子。

 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' 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM