1 var name = "The Window"; 2 var object = { 3 name : "My Object", 4 getNameFunc : function(){ 5 return function(){ 6 return this.name; 7 }; 8 } 9 };
一个经典的代码,在高程也出现过的,意在说明 this 和 闭包变量作用域。
以前写过一篇记录一下,最近在sf看到一博客文章,又突然陷入深思。
http://blog.segmentfault.com/findingea/1190000000537129
首先,说一下2个关键点:
1.function的作用域:在function中访问一变量,首先看function执行体内是否存在该变量,不存在,则往function的调用环境,去查询,如果是多层调用,则会遵循内部找不到就往外部查找,一直到全局作用域,这也就是作用域链。
1.1一般说来,闭包,即内部函数调用了外部函数的变量,并返回自身给外部使用,此时,即可访问到外部函数的变量,这里能不能说其实也是套用了所谓的作用域链原理呢。
2. function的作用域内,本身执行体的执行环境包含参数arguments和this两个自带的,不会导致需要去外部找变量,上面的经典问题中,this.name之所以返回的是 the window 即全局变量,那是因为function自身的调用环境决定的,这个return的闭包,不属于object对象本身的属性,因此,自然而然,其调用主题是全局window。
通过需要后,即可达到访问object.name的效果.
1 var name = "The Window"; 2 var object = { 3 name : "My Object", 4 getNameFunc : function(){ 5 var that = this; 6 return function(){ 7 return that.name; 8 }; 9 } 10 };
这里用that存了this,getNameFunc本身就是object的属性,因此this指向的是object,而that作为最底层的function的外部函数的作用域之一,刚好function内部没有that的申明,所以自然内部调用that访问的就是外部函数的作用域的that。
而我本来觉得这样好理解,突然想,那么不要this呢?
1 var name = "The Window"; 2 var object = { 3 name : "My Object", 4 getNameFunc : function(){ 5 return function(){ 6 return name; 7 }; 8 } 9 };
一开始以为,根据作用域链,最终得到的name应该是object.name,结果一运行,不对,为什么呢?
一开始搞不明白。
但是,回想起来,首先,getNameFunc这里如果调用name同样得到的是全局的name. 想想,假设我加一句代码进去,
1 var name = "The Window"; 2 var object = { 3 name : "My Object", 4 getNameFunc : function(){ 5 console.log(name); //这里name是全局name 6 return function(){ 7 return name; 8 }; 9 } 10 };
正如我注释的那里,这里直接调用name,跟调用this.name的不同,在于this.name是对象的属性,直接调用,则是查找作用域里声明的name,明显与对象属性不是同一个概念,正如
var name = 0; 和 obj.name="dont"; 不能相提并论,不知道这么解释对不对。
也正因为作用域里不存在独立的name声明,因此最终找到的是全局的作用域声明的name: The Window.