旋量群
旋量群表述:指保有数个函数和存取了那些函数的自然环境的函数(一般来说是两个函数),因此那些函数也是该函数的一小部分。函数内部能间接加载全局函数。函数内部函数难以在函数内部出访。函数内部新闻稿要用var或是let新闻稿,要不然会变为全局函数拉艾返回值:子第一类会二级级向下找寻父第一类的函数,父第一类的函数子第一类都是由此可见的,但若则没用。在两个旋量群自然环境内修正函数值,不能负面影响另两个旋量群中的函数。一般的函数嵌入,内部函数是先继续执行;而旋量群则是:先把内部函数Kozhikode内部函数,接着在继续执行。
上面这段标识符是两根众所周知的旋量群
function f1(){
var a =10;
function f2(){
alert(a);
}
f2();//①
}
f1();
//10 ②
f1和f1()的区别不加括号是标识符,加()是继续执行这段标识符,加return是返回两个值,能把返回的值赋值给函数,不加return默认返回undefined;所以①处有三种写法:
第一种:①处写f2();,②处调用需要这样写f1();。具体继续执行过程:f1体内调用f2函数,并继续执行。
第二种:①处写return f2();,②处调用需这样写f1();。具体继续执行过程:同上;区别是多了个return,因为现在f2函数中没有返回值,所以f1在调用f2只是继续执行一下alert(a),f1的返回值是undefined
第三种:①处写return f2;,②处调用需这样写f1()();。这里返回的是f2函数的标识符,所以在调用f1时要加上2个括号,第两个括号是继续执行f1函数,第2个括号是继续执行f2函数,如果①处省略return会报错。return和函数调用时是否加括号的意思都知道,但是把它俩结合起来,就搞不清了。正好今天学旋量群时碰上了,顺便就把它搞清楚了。
到底什么是旋量群
对于新人(当然了是说我了),看很多旋量群的表述,标识符,还是不知啥是旋量群,云里雾里的,这里感谢方方老师的文章JS 中的旋量群是什么?,看完后,虽然还是说不出啥是旋量群,但现在已经知道啥是旋量群了,果然用图说话最牛逼。(图在文章中,我就不放出来了)
旋量群的应用
MDN 上这个例子也写的很好
调用Counter.value()时,返回的是Counter内部的函数privateCounter;increment内部没有返回值,这个方法只是继续执行了privateCounter + 1操作,没有返回值;同理decrement是将privateCounter – 1,也没有返回值;
所以继续执行Counter.increment,会返回undefined,但是接着操作Counter.value()时就能得到1,因为继续执行上一步Counter.increment时privateCounter被+1了。
今天在上面三段标识符上花费了大量的时间,一直似懂非懂,心里不踏实。
标识符一:
var name =window;var obj ={
name:object,
getName:function(){
returnthis.name;
}};
obj.getName();
//object(obj.getName = obj.getName)();
//window 非严格模式下
标识符二:
var name =window;var obj ={
name:object,
getName:function(){
returnfunction(){
returnthis.name;
}
}};
obj.getName()();
//window
标识符三:
var name =window;
var obj ={
name :object,
getName :function(){
var that =this;
returnfunction(){
return that.name;
};
}
};
obj.getName()();//object
今天在看阮一峰的博客学习Javascript旋量群(Closure),对标识符二、标识符三部分很是不解,看到一网友搬出犀牛书(还没看过,我买了红宝石书才看了一点点)里的话,实在不解什么是作为函数调用,什么是作为方法调用;
《Javascript权威指南》上说:如果嵌套函数作为函数调用,其this值不是全局第一类(非严格模式下)是undefined(严格模式下); 如果嵌套函数作为方法调用,其this值指向调用它的第一类。
又有一位网友说
每个函数在被调用时,其活动第一类都会自动取得两个特殊函数:this和arguments。内部函数在搜索这个函数时,只会搜索到其活动第一类为止,因此永远不可能间接出访内部函数中的这两个函数(这一点通过前面的图能看得更清楚)。意思是说找到匿名函数中的this和arguments就不能再往下找了(这里的往下指的是外层的包含函数,和最外层的window全局自然环境),而匿名函数的this第一类一般来说指向window,所以输出的是全局的那个字符串。不过,把内部返回值中的this第一类保存在两个旋量群能够出访到的函数里,就能让旋量群出访该第一类了。
看到这里大概知道匿名函数的返回值是全局,继续翻看上面评论,大概意思是说“把this保存在obj返回值下的两个函数中,this就在当前函数的返回值下了”。直到看完也是,似懂非懂,反正是感觉哪里不对劲,但也说不上了。
直到看到【JavaScript】【函数】旋量群旋量群!这篇文章的标识符一小部分,总算知道其中的逻辑了。
上面就来分析其中的逻辑,我分析的方法是把不懂的地方两个个用console打印出来标识符二和标识符一的区别是多了一层嵌套函数,this值就不一样了。
ps:我一开始以为在标识符二中再嵌套一层函数,就会打印出object=_=|||
先来看标识符一,知道之后,另外两段标识符自然就懂了。
为什么obj.getName()打印出来的是object,
因为这时getName方法是在obj的返回值下,所以this指向obj,返回值当然是object了。
接着看(obj.getName = obj.getName)()删掉右边后,打印出的结果变为了object,这就纳闷了。
ps:第一眼看上去,这啥玩意,把自己赋值给自己?这不是多此一举,间接用不就行了!用console.log打印出obj.getName后,总算拨云见天,obj.getName = obj.getName这句话的意思是把getName函数赋值给自己,这个时候就不是obj.getName,而是getName匿名函数了,匿名函数一般来说用的方法是()()立即继续执行,此时再看匿名函数已经脱离obj了,当然this也就指向了全局,打印出window。
再来看代码二,用console打印出obj.getName()会发现是两个匿名函数,而匿名函数的this一般来说会指向全局,所以也就不难理解了理解上面两段标识符,标识符三也就很好理解了。
旋量群中引用循环函数
旋量群在文中就很形象的讲解了函数中的引用会变化的函数会有什么后果,我节选了他的结论和标识符。
返回旋量群时牢记的一点是:返回函数不要引用任何循环函数,或是后续会发生变化的函数。如果一定要引用循环函数怎么办?方法是再创建两个函数,用该函数的参数存取循环函数当前的值,无论该循环函数后续如何更改,已存取到函数参数的值不变:
function count(){
var arr =[];
for(var i=1; i<=3; i++){
arr.push((function(n){
returnfunction(){
return n * n;
}
})(i));
}
return arr;
}
var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];
f1();// 1
f2();// 4
f3();// 9
博客网址:www.xiaoyabaxin.com