范围链查找vs原型查找 - 这是什么时候 [英] Scope chain look-up vs prototype look-up - Which is when

查看:130
本文介绍了范围链查找vs原型查找 - 这是什么时候的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果一个变量在需要时在函数中不可用,那么它在范围链中(这是一个闭包)被查找,但有时候它在原型链中被搜索。我试图包裹我的头发生在什么时候发生。我想知道是否有人能为我清除雾气,或者让我参考一些文献,特别讨论这个话题。



例如,我说的是正确的:
- 对象,因此绑定到上下文的公共变量(this)总是在原型链中查找?
- 私有变量总是在范围链中查找(即执行上下文中的函数链)? - 是否有任何情况下,程序正在两个/两个?



我测试了三种不同的场景(范围链查找,原型查找,

  var Food = function(){ 
var t = 1; // for closure

this.timeToPrepare = function(){//范围链查找
console.log(t * 3);
};

this.timeToMake = function(){//这是在原型链中查找的
console.log(this.t * 3);
};

this.timeToEat = function(t){//没有查找
console.log(t * 3);
};

};

Food.prototype.t = 2;

(function(){
var pizza = new Food;
pizza.timeToPrepare(); // 3
pizza.timeToMake(); // 6
pizza.timeToEat(3); // 9
})();



谢谢!

解决方案

会在范围链上查找,从当前执行上下文开始,向上移动包含执行上下文的树。



属性首先在基础对象上查找,然后在该对象的 [[Prototoype]]


$ b

$ c> foo

foo 将被视为变量,在范围链上。变量名从不限定,不能将它们定向到要查找的特定执行上下文。如果范围链上有两个具有相同名称的变量,则只能访问在第一次访问时首次遇到的变量链接(有一个方法围绕这个专门为全局变量),例如

  var a ='global a'; 

function foo(){
var a ='local a';
return a;
}

console.log(foo()); // local a

在上面的函数中, a 局部变量 a 。在全局变量的情况下,它们是全局对象的属性,所以你可以访问它们,即使它们被同一个命名的本地属性隐藏,例如

  function foo(){
var ='local a';
//这将引用全局对象
return this.a;
}

console.log(foo()); // global a

相比之下,属性名称前面总是有一个基础对象(如上例所示, 引用全局对象),例如

  foo。 bar 

将拆分为 foo bar 。首先, 将在范围链上解析,如果找到,属性解析将尝试找到一个 bar 属性。所以对于属性,你可以指定属性被查找的对象。因此,如果有两个具有相同命名属性的对象,只要两个对象都在作用域中,就可以查找这两个对象。



因此,任何引用的第一部分作为变量处理,随后的部分被视为属性。除非使用,但不鼓励。

但是为了完整性... 将指定的对象放在开始范围链上,这样变量首先被查找为所以你可以这样做:

  var cos = function(arg){return'my cos函数:'+ arg}; 

function foo(){

// cos在范围链上被解析
console.log(cos(0.5)); // my cos function:0.5

with(Math){
// cos首先被解析为Math的属性,并且只有在
// scope链上发现有
console.log(cos(0.5))// 0.8775825618903728
}
}

foo();


If a variable is not available in a function when it's needed, then it's being looked for in the scope chain (which is a closure), but other times it's being searched for in the prototype chain. I am trying to wrap my head around which is happening when. I was wondering if someone could kindly clear the mist for me, or refer me to some literature discussing this topic specifically.

For example, would I be right saying that: - Objects and therefore public variables tied to the context (this)are always looked up in the prototype chain? - Private variables are always looked up in the scope chain (i.e. chain of functions in the execution context)? - Are there any cases when the program is looking in both/either?

I tested three different scenarios(scope chain look-up, prototype look-up and no look-up), but unfortunately It haven't helped enough to get to the bottom of this.

    var Food = function(){
    var t = 1;  // for closure

    this.timeToPrepare = function(){    // Scope chain lookup
        console.log(t * 3);
    };

    this.timeToMake = function(){   // This is looked up in the prototype chain
        console.log(this.t * 3);
    };

    this.timeToEat = function(t){   //No lookup
        console.log(t * 3);
    };

    };

    Food.prototype.t = 2;

    (function(){
    var pizza = new Food;
    pizza.timeToPrepare();  //3
    pizza.timeToMake();     //6
    pizza.timeToEat(3);     //9
    })();

Thanks!

解决方案

Variables are looked up on the scope chain, starting with the current execution context and going up the tree of enclosing execution contexts.

Properties are looked up firstly on the base object, then on that object's [[Prototoype]] chain (i.e. its internal prototype).

So if you do:

foo

foo will be treated as a variable and looked up on the scope chain. Variable names are never qualified, you can't direct them to a specific execution context to be looked up in. If there are two variables on the scope chain with the same name, you can only access the one that is first encountered when going along the chain (there is a way around this specifically for global variables), e.g.

var a = 'global a';

function foo() {
  var a = 'local a';
  return a;
}

console.log(foo()); // local a

In the above, a within the function resolves to the local variable a. In the case of global variables, they are made properties of the global object so you can access them even if they are "shadowed" by a same named local property, e.g.

function foo() {
  var = 'local a';
  // this will reference the global object
  return this.a;
}

console.log(foo()); // global a

In contrast, property names are always preceded by a base object on which they are looked up (as in the example above, where this references the global object), e.g.

foo.bar

will be split into foo and bar. Firstly, foo will be resolved on the scope chain and, if found, property resolution will try to find a bar property. So for properties, you can direct which object the property is looked up on. So if there are two objects with a same named property, you can look up both properties as long as both objects are in scope.

So the first part of any reference is treated as a variable, the subsequent parts are treated as properties. Except when with is used, but that is discouraged. Don't go there.

But for completeness… with places the specified object on the start scope chain so that variables are first looked up as properties of that object before using the scope chain, so you can do:

var cos = function(arg){return 'my cos function: ' + arg};

function foo() {

  // cos is resolved on the scope chain
  console.log(cos(0.5));  // my cos function: 0.5

  with (Math) {
    // cos is first resolved as a property of Math, and only on the
    // scope chain if not found there
    console.log(cos(0.5)) // 0.8775825618903728
  }
}

foo();

这篇关于范围链查找vs原型查找 - 这是什么时候的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆