1 var name = "The Window"; 2 function Mly(){ 3 this.name="My Object"; 4 this.getNameFunc=function(){ 5 return function(){ 6 alert(this);//[object Window] 7 return this.name; 8 }; 9 }; 10 } 11 var object=new Mly(); 12 alert(object.getNameFunc()()); //The Window 13 //为什么alert(this);打印的是[object Window]而不是[object Object]??? 14 //为什么alert(object.getNameFunc()());打印的是The Window而不是My Object???
object.getNameFunc()() 分解一下: object.getNameFunc(),这个返回一个function 则是(f是没有的,假设一个名字)var f=function(){alert(this);return this.name} 然后再执行f();这个时候f的作用域就是window了。 要想返回[object Object],'My Object',需要指定一下作用域:alert(object.getNameFunc().apply(object));
提供两个例子:
var name = "The Window"; function Mly() { this.name = "My Object"; this.getNameFunc = function() { alert(this); return this.name; } } var obj = new Mly(); alert(obj.getNameFunc());
var name = "The Window"; function aaa() { alert(this); return this.name; } function Mly() { this.name = "My Object"; this.getNameFunc = function() { return aaa; } } var obj = new Mly(); alert(obj.getNameFunc()());
看看下面的内容,你就知道是为什么了
作用域链(Scope Chains)
作用域链的原理和原型链很类似,如果这个变量在自己的作用域中没有,那么它会寻找父级的,直到最顶层。
标示符[Identifiers]可以理解为变量名称、函数声明和普通参数。例如,当一个函数在自身函数体内需要引用一个变量,但是这个变量并没有在函数内部声明(或者也不是某个参数名),那么这个变量就可以称为自由变量[free variable]。那么我们搜寻这些自由变量就需要用到作用域链。
在一般情况下,一个作用域链包括父级变量对象(variable object)(作用域链的顶部)、函数自身变量VO和活动对象(activation object)。
当查找标识符的时候,会从作用域链的活动对象部分开始查找,然后(如果标识符没有在活动对象中找到)查找作用域链的顶部,循环往复,就像作用域链那样。
我们假设作用域链的对象联动是通过一个叫做__parent__的属性,它是指向作用域链的下一个对象。这可以在Rhino Code中测试一下这种流程,这种技术也确实在ES5环境中实现了(有一个称为outer链接).当然也可以用一个简单的数据来模拟这个模型。使用__parent__的概念,我们可以把上面的代码演示成如下的情况。(因此,父级变量是被存在函数的[[Scope]]属性中的)。
图 9. 作用域链