匿名函数具名化【官方推荐规范】
- 应该是匿名函数的
- 自执行函数
- 函数表达式
- 回调函数 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); //undefined
var A = 100;
console.log(A); //100
})();
/*
* EC(AA)
* A--------->函数本身
* 作用域链
* 形参赋值 A ===100
* 变量提升:---
*/
(function A(A) {
console.log(A); //100
A = 200;
console.log(A); //200
})(100);
(function A(A) {
console.log(A); //100
function 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();