范围链查找与原型查找 - 何时

Cro*_*ile 11 javascript closures scope-chain prototypal-inheritance

如果变量在需要时在函数中不可用,那么它将在作用域链中查找(这是一个闭包),但有时它会在原型链中进行搜索.我正试着把头包裹起来,当时正在发生这种情况.我想知道是否有人可以为我清除薄雾,或者让我参考一些专门讨论这个主题的文献.

例如,我是否正确地说: - 对象和因此与上下文绑定的公共变量(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
    })();
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

谢谢!

Rob*_*obG 18

在作用域链上查找变量,从当前执行上下文开始,然后向上查找封闭执行上下文的树.

首先在基础对象上查找属性,然后在该对象的[[Prototoype]]链(即其内部原型)上查找属性.

所以,如果你这样做:

foo
Run Code Online (Sandbox Code Playgroud)

foo将被视为变量并查看范围链.变量名永远不会被限定,您无法将它们定向到要查找的特定执行上下文.如果作用域链上有两个具有相同名称的变量,则只能访问首次遇到的变量.链(有一种方法专门用于全局变量),例如

var a = 'global a';

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

console.log(foo()); // local a
Run Code Online (Sandbox Code Playgroud)

在上文中,一个在函数内解析到本地变量一个.在全局变量的情况下,它们是全局对象的属性,因此即使它们被相同的命名本地属性"遮蔽",您也可以访问它们,例如

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

console.log(foo()); // global a
Run Code Online (Sandbox Code Playgroud)

相反,属性名称前面总是有一个查找它们的基础对象(如上例所示,引用了全局对象),例如

foo.bar
Run Code Online (Sandbox Code Playgroud)

将分为foobar.首先,foo将在范围链上解析,如果找到,属性解析将尝试查找bar属性.因此,对于属性,您可以指示查找属性的对象.因此,如果有两个具有相同命名属性的对象,只要两个对象都在范围内,就可以查找这两个属性.

因此,任何引用的第一部分都被视为变量,后续部分被视为属性.除了当被使用,但不鼓励.不要去那里.

但为了完整性...... 地方上的启动作用域链指定的对象,这样的变量是第一次看到了作为对象的属性使用范围链之前,所以你可以这样做:

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();
Run Code Online (Sandbox Code Playgroud)