84669 orang belajar
152542 orang belajar
20005 orang belajar
5487 orang belajar
7821 orang belajar
359900 orang belajar
3350 orang belajar
180660 orang belajar
48569 orang belajar
18603 orang belajar
40936 orang belajar
1549 orang belajar
1183 orang belajar
32909 orang belajar
闭关修行中......
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这个变量,你可以把变量写到对象里面去。