提问人:Crocodile 提问时间:12/12/2014 更新时间:12/12/2014 访问量:2896
范围链查找与原型查找 - 何时
Scope chain look-up vs prototype look-up - Which is when
问:
如果某个变量在需要时在函数中不可用,则在作用域链(这是一个闭包)中查找该变量,但其他时候则在原型链中搜索该变量。我试图弄清楚什么时候发生。我想知道是否有人可以为我清除迷雾,或者向我推荐一些专门讨论这个话题的文献。
例如,我说得对吗: - 对象和与上下文(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
})();
谢谢!
答:
变量在作用域链上查找,从当前执行上下文开始,一直到封闭执行上下文的树。
首先在基对象上查找属性,然后在该对象的链(即其内部原型)上查找属性。[[Prototoype]]
因此,如果您这样做:
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';
// this will reference the global object
return this.a;
}
console.log(foo()); // global a
相反,属性名称总是在查找它们的基本对象之前(如上面的示例所示,其中引用全局对象),例如
foo.bar
将分为 foo 和 bar。首先,foo 将在作用域链上解析,如果找到,属性解析将尝试找到一个柱属性。因此,对于属性,您可以指示查找属性的对象。因此,如果有两个对象具有相同的命名属性,则只要两个对象都在作用域内,就可以查找这两个属性。
因此,任何引用的第一部分都被视为变量,后续部分被视为属性。除非使用 with,但不鼓励这样做。不要去那里。
但为了完整起见......with 将指定的对象放在起始作用域链上,以便在使用作用域链之前首先将变量作为该对象的属性进行查找,因此您可以执行以下操作:
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();
评论
this
t
t
var t
call
apply
bind