函数的执行环境与调用对象
javascript高程3版中在闭包中关于this有一个这样的例子。
1 var name = "The Window"; 2 3 var object = { 4 name : "My Object", 5 6 getNameFunc : function(){ 7 return function(){ 8 return this.name; 9 }; 10 } 11 }; 12 13 alert(object.getNameFunc()()); //"The Window"
解释有这样一句话,“匿名函数的执行环境具有全局性,因此其this对象通常指向window”,这句话很容易误解。执行环境是什么?在作用域链那一章提到函数的执行环境是指执行流进入函数时它内部的区域,作用域链是该执行环境有权访问的数据的范围。显然,这和匿名函数的“执行环境”说的不是一回事。
函数的作用域,取决于函数创建的地方,与调用对象无关,也与调用语句的位置无关。同样地,this的指向在函数创建的时候是决定不了的,在调用的时候才能决定,谁调用的就指向谁,这是三个完全不同的概念。关于this的指向和函数运行时的执行环境,这两篇写的很详细:
http://www.cnblogs.com/pssp/p/5216085.html
http://www.cnblogs.com/mfc-itblog/p/5736600.html
再回到最开始这个例子,英文版原文是“Anonymous functions are not bound to an object in this context, meaning the this object points to window”.即是说这里第二个括号()是直接运行返回的匿名函数,它并没有被任何对象调用(object.只调用母函数),于是就指向了windows。完全没提到匿名函数的什么全局性,实际上这里和匿名不匿名关系不大,this主要是跟调用函数的对象挂钩。
第二个例子:
这也是书上的原例题,稍有改动。在讲call()方法的这一节,中文版写的是能够扩充函数赖以运行的作用域,又是一头雾水。英文原文:“their ability to augment the this value inside of the function”显然是说可以扩展this的取值,或者说可以召唤别的对象来调用这个函数。作用域是指能访问数据的范围,当然这里确实可以访问更多的数据了,比如原来对象O的color属性是访问不到的,现在通过sayColor.call(o)可以获得this.color了,然而它的本质还是因为this的取值扩展了,而不是函数的作用域改变或是扩展了。如果我要直接获取某个变量,可以看到当执行alert(color)的时候,显示的是wrap中的yellow,这是由创建代码的位置决定的,这个color在sayColor的作用域链中。
即使把wrap的color注释掉,依然是获取不到o里面的color的,因为它根本不在sayColor的作用域链里,要想取到它的属性值必须前缀this。