匿名函数具名化【官方推荐规范】
- 应该是匿名函数的
- 自执行函数
- 函数表达式
- 回调函数 setTimeout(function(){},1000)
匿名函数具名化特点
1.设置的名字,并不会在所处上下文中进行声明
(function A() {// ...})();console.log(A); //Uncaught ReferenceError: A is not defined
2.在函数执行形成的私有上下文中,会把这个名字作为一个私有变量「存储到AO中」,变量值是当前函数本身「堆内存地址」; 并且默认情况下,对这个变量值进行修改是无效的;
(function A() {A = 100; //无效操作console.log(A); //函数本身})();
3.但凡函数内部,这个名字被我们手动的声明过「例如:形参/var/function/let/const…」,都认为这个名字是我们自己玩的私有变量,和默认值是当前函数本身没关系了!! “默认是函数本身的这个点,权重太低”
/** EC(AA)* A--------->函数本身* 作用域链* 形参赋值--* 变量提升:var A*/(function A() {console.log(A); //undefinedvar A = 100;console.log(A); //100})();/** EC(AA)* A--------->函数本身* 作用域链* 形参赋值 A ===100* 变量提升:---*/(function A(A) {console.log(A); //100A = 200;console.log(A); //200})(100);(function A(A) {console.log(A); //100function A(){}console.log(A); //200})(100);/*/!** EC(G)* b --> 10** 变量提升: var b;*!/var b = 10;(function b() {/!** EC(B) 私有上下文* b --> 当前函数本身* 作用域链:<EC(B),EC(G)>* 形参赋值:--* 变量提升:--*!/b = 20; //无效操作console.log(b); //当前函数本身})();console.log(b); //10
匿名函数具名化作用:
因为我们可以在函数内部,基于这个名字访问到这个函数,这样就可以实现一些原本不具备的能力,例如:递归
“use strict”; 开启JS严格模式「语法要更加严谨,目前我们开发,基于webpack打包后,都是严格模式」
"use strict";(function () {// 递归?// arguments.callee:代表当前函数本身// arguments.callee.caller:存储函数在哪执行的// 但是在严格模式下,都嗝屁了,不允许使用....console.log(arguments);})();(function A() {// 实现递归处理// console.log(A); //函数本身A();})(); //死递归 内存溢出
了解arguments.callee 和arguments.callee.caller
- arguments.callee:指的是函数本身
- arguments.callee.caller 指的是函数执行的宿主环境,如果是在函数A中执行,打印出来的就是A,如果是在全局作用域中执行,打印出来的就是null。
function fn(){console.log(arguments.callee); // 打印出的是fn 函数本身}fn();function fn(){console.log(arguments.callee.caller);}fn(); // 此时打印出的是 null(在全局作用域中执行)function fn(){console.log(arguments.callee.caller);}function A(){fn(); // 此时打印出的是 A这个函数}A();
