闭关修行中......
this是跟著函式呼叫而产生的,它的范围是以函式为界限,谁(某物件)呼叫了这个函式,谁(某物件)就是this,与函式是在全域定义或物件字面定义无关,与呼叫函式是谁才有关。总个来说明,作用域是静态的,但this的建立却是动态的。
this
所以,像这个呼叫:
object.getNameFunc()
对getNameFunc函式来说,this的确是object,也就是说当你的程式码改为下面的写法,就可以获得object.name,因为此时的this相当于object:
getNameFunc
object
object.name
var object = { name:'bb', getNameFunc2: function(){ return this.name; } } console.log(object.getNameFunc2()); //bb
当函式中没有明确的呼叫它的对象,在旧的情况下,this值默认为为window物件也就是全域物件,在新的标准中或是用严格模式(strict code)时,是undefined,刚上面说过this是以函式为界限。所以你在内部(巢状)函式里的下面这个函式呼叫,很明显的它的this值必然是默认情况:
window
undefined
return function(){ return this.name; }();
你的结果会得到aa的值,是因为不在严格模式(strict code)下,如果在严格模式或较新式写法中,是会发生错误而无法得到值,因为呼叫者是undefined,也就是不存在。aa是属于全域变数,或是window物件中的变数值。
而由于上面的这些知识,你可以利用内部(巢状)函式能够取得外部函式的变数作用域的特点,也就是闭包的特性,这种特性是因为作用域的连锁而来。进一步来修正内部函式的this值,所以可以用下面的解决方式,用一个中继的变数来转介外部函式的this值,下面的改写中的that并非一定要叫这个名称,有人喜好用self或_that,实际上都行:
that
self
_that
var object = { name:'bb', getNameFunc: function(){ var that = this return function(){ return that.name; }(); } }
另一种改写方式是视情况使用函式的call或bind,它们可以在第一个传参中使用一个物件,以此改变函式呼叫(或执行)的上下文,也就是this值。
call
bind
var object = { name:'bb', getNameFunc: function(){ return function(){ return this.name; }.call(this); } }
由上面的实作可得知,内部函式的闭包结构,并不会传递外部函式的this值,因为this的设计是以函式为界限。提外话是,你可能也想知道函式的隐藏arguments物件会不会被传递,答案是当然也不会。
最后,你可能不知道在物件里面可以呼叫物件本身,所以下面的写法也是可行的,但它与this无关,只是JavaScript里可以这样作而已:
var object = { name:'bb', getNameFunc: function(){ return function(){ return object.name; }(); } }
你可以说他是个设计缺陷但它也存在几十年了,与其等待改变或直接放弃,不如先了解是什么。
详细的内容可以参考小弟整理的ES6电子书,在gitbook上,繁体的供参考:
闭包: https://eyesofkids.gitbooks.i...
this: https://eyesofkids.gitbooks.i...
方法是谁调用的谁就是this。这个列子里面,object.getNameFunc()返回了一个自执行函数
function(){ return this.name; }()
此时调用者为window,故this为window。
var object = { name:'bb', getNameFunc: function(){ return: function(){ return: this.name; }(); } }
分析一下作用域 全局中object -- > object里面的name/getNameFunc --> getNameFunc函数 -- > 返回函数的立即调用。
object.getNameFunc()调用 ---- 返回一个函数的调用,独立函数调用会采用默认绑定规则绑定到全局作用域中
推荐看《你不知道的js》里面有详细的介绍
这个问题,并不是说闭包函数的this一定指向全局,而是函数作用域的问题,一个匿名函数作为返回值,这个匿名函数在执行时已经脱离了原来的scope,作用域变为了全局,this自然指向全局。js中有很多这种情况,比如最常见的回调函数。
这与this是不是在闭包中没有直接关系的,this的指向取决于函数的执行环境,getNameFunc函数中的this指向是object,但是getNameFunc函数中的匿名函数是一个独立的执行环境,该匿名函数没有明确的调用者,所以默认执行环境是window。
关于闭包,闭包是可以访问外部作用域的变量,我认为题主所疑惑的是闭包里已经访问外部this,所以返回的应该是bb,但是this并不是一个变量,它会随着执行环境的变更而变更。
没明确定义在某个对象上的函数都是全局函数,隶属于全局对象。
默认都是指向全局对象的,浏览器是window。你这个code应该
var object = { name:'bb', getNameFunc: function(){ var that=this; return function(){ return that.name; } } }
var object = { name:'bb', getNameFunc: function(){ return function(obj){ return obj.name; }(this) } }
因为闭包里的this指向window,你可以在闭包里console.log(this)一下,会发现输出window。至于为什么闭包里的this会指向window,我还分析不出。不过这个结果请牢记。
因为你定义的name变量本身就是个全局变量,而你对象里面又没有定义有相同的变量名,JavaScript会依次从内部外部寻找name这个变量,你可以把变量写到对象里面去。
this
是跟著函式呼叫而产生的,它的范围是以函式为界限,谁(某物件)呼叫了这个函式,谁(某物件)就是this
,与函式是在全域定义或物件字面定义无关,与呼叫函式是谁才有关。总个来说明,作用域是静态的,但this
的建立却是动态的。所以,像这个呼叫:
对
getNameFunc
函式来说,this
的确是object
,也就是说当你的程式码改为下面的写法,就可以获得object.name
,因为此时的this
相当于object
:当函式中没有明确的呼叫它的对象,在旧的情况下,
this
值默认为为window
物件也就是全域物件,在新的标准中或是用严格模式(strict code)时,是undefined
,刚上面说过this
是以函式为界限。所以你在内部(巢状)函式里的下面这个函式呼叫,很明显的它的this
值必然是默认情况:你的结果会得到aa的值,是因为不在严格模式(strict code)下,如果在严格模式或较新式写法中,是会发生错误而无法得到值,因为呼叫者是
undefined
,也就是不存在。aa是属于全域变数,或是window
物件中的变数值。而由于上面的这些知识,你可以利用内部(巢状)函式能够取得外部函式的变数作用域的特点,也就是闭包的特性,这种特性是因为作用域的连锁而来。进一步来修正内部函式的
this
值,所以可以用下面的解决方式,用一个中继的变数来转介外部函式的this
值,下面的改写中的that
并非一定要叫这个名称,有人喜好用self
或_that
,实际上都行:另一种改写方式是视情况使用函式的
call
或bind
,它们可以在第一个传参中使用一个物件,以此改变函式呼叫(或执行)的上下文,也就是this
值。由上面的实作可得知,内部函式的闭包结构,并不会传递外部函式的
this
值,因为this
的设计是以函式为界限。提外话是,你可能也想知道函式的隐藏arguments物件会不会被传递,答案是当然也不会。最后,你可能不知道在物件里面可以呼叫物件本身,所以下面的写法也是可行的,但它与this无关,只是JavaScript里可以这样作而已:
你可以说他是个设计缺陷但它也存在几十年了,与其等待改变或直接放弃,不如先了解是什么。
详细的内容可以参考小弟整理的ES6电子书,在gitbook上,繁体的供参考:
闭包: https://eyesofkids.gitbooks.i...
this: https://eyesofkids.gitbooks.i...
方法是谁调用的谁就是this。
这个列子里面,object.getNameFunc()返回了一个自执行函数
此时调用者为window,故this为window。
分析一下作用域 全局中object -- > object里面的name/getNameFunc --> getNameFunc函数 -- > 返回函数的立即调用。
object.getNameFunc()调用 ---- 返回一个函数的调用,独立函数调用会采用默认绑定规则绑定到全局作用域中
推荐看《你不知道的js》里面有详细的介绍
这个问题,并不是说闭包函数的this一定指向全局,而是函数作用域的问题,一个匿名函数作为返回值,这个匿名函数在执行时已经脱离了原来的scope,作用域变为了全局,this自然指向全局。js中有很多这种情况,比如最常见的回调函数。
这与
this
是不是在闭包中没有直接关系的,this
的指向取决于函数的执行环境,getNameFunc
函数中的this指向是object,但是getNameFunc
函数中的匿名函数是一个独立的执行环境,该匿名函数没有明确的调用者,所以默认执行环境是window
。关于闭包,闭包是可以访问外部作用域的变量,我认为题主所疑惑的是闭包里已经访问外部
this
,所以返回的应该是bb,但是this
并不是一个变量,它会随着执行环境的变更而变更。没明确定义在某个对象上的函数都是全局函数,隶属于全局对象。
默认都是指向全局对象的,浏览器是window。
你这个code应该
因为闭包里的this指向window,你可以在闭包里console.log(this)一下,会发现输出window。至于为什么闭包里的this会指向window,我还分析不出。不过这个结果请牢记。
因为你定义的name变量本身就是个全局变量,而你对象里面又没有定义有相同的变量名,JavaScript会依次从内部外部寻找name这个变量,你可以把变量写到对象里面去。