javascript关于this对象,在闭包函数中为什么会引用全局变量
问题描述
this
是跟著函式呼叫而产生的,它的范围是以函式为界限,谁(某物件)呼叫了这个函式,谁(某物件)就是this
,与函式是在全域定义或物件字面定义无关,与呼叫函式是谁才有关。总个来说明,作用域是静态的,但this
的建立却是动态的。
所以,像这个呼叫:
object.getNameFunc()
对getNameFunc
函式来说,this
的确是object
,也就是说当你的程式码改为下面的写法,就可以获得object.name
,因为此时的this
相当于object
:
var object = {
name:'bb',
getNameFunc2: function(){
return this.name;
}
}
console.log(object.getNameFunc2()); //bb
当函式中没有明确的呼叫它的对象,在旧的情况下,this
值默认为为window
物件也就是全域物件,在新的标准中或是用严格模式(strict code)时,是undefined
,刚上面说过this
是以函式为界限。所以你在内部(巢状)函式里的下面这个函式呼叫,很明显的它的this
值必然是默认情况:
return function(){
return this.name;
}();
你的结果会得到aa的值,是因为不在严格模式(strict code)下,如果在严格模式或较新式写法中,是会发生错误而无法得到值,因为呼叫者是undefined
,也就是不存在。aa是属于全域变数,或是window
物件中的变数值。
而由于上面的这些知识,你可以利用内部(巢状)函式能够取得外部函式的变数作用域的特点,也就是闭包的特性,这种特性是因为作用域的连锁而来。进一步来修正内部函式的this
值,所以可以用下面的解决方式,用一个中继的变数来转介外部函式的this
值,下面的改写中的that
并非一定要叫这个名称,有人喜好用self
或_that
,实际上都行:
var object = {
name:'bb',
getNameFunc: function(){
var that = this
return function(){
return that.name;
}();
}
}
另一种改写方式是视情况使用函式的call
或bind
,它们可以在第一个传参中使用一个物件,以此改变函式呼叫(或执行)的上下文,也就是this
值。
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...
这篇关于javascript关于this对象,在闭包函数中为什么会引用全局变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!