匿名函数具名化

671 阅读2分钟

arguments.callee 应用场景

表示的是函数本身,用于递归调用

let obj = {
    name:'john',
    fn:function(n){
        console.log(this)
        n++;
        if(n>15) return;
        console.log(n)
        obj.fn(n); // 调用自己 这样也可以 跟下面的区别是this的指向不同 this -> obj
        
        arguments.callee(n) // this 是 arguments 
    }
}
obj.fn()

(function(i){
    if(i>=3) return;
    arguments.callee(++i)  // 这种情况下只能用arguments.callee()
})(1)

但是JS严格模式下,不支持arguments.callee(),此时我们该如何实现匿名函数下的递归呢?

即 匿名函数“具名化”

匿名函数“具名化”定义

给函数表达式的函数起的名字。 匿名函数“具名化”是非常规范的操作

作用和特点

防止全局污染

  • 此名字不能在外面访问,也就是不会在当前上下文中创建这个名字。当函数执行,在形成的私有上下文中,会把这个具名化的名字作为私有上下文中的变量(值就是这个函数)来进行处理。

  • 在本函数的上下文中使用,它的值是不会被修改的。(有特殊性)

  • 除非当前的名字被上下文中的其他变量声明过,则名字是私有变量,和具名化的函数没有任何的关系了。这个时候才可以更改。

    var func = function AAA(){
        // 当函数执行,在形成的私有上下文中,会把这个具名化的名字作为私有上下文中的变量(值就是这个函数)来进行处理。 
        console.log(AAA)
        // AAA()  递归调用,而不用严格模式下都不支持的 arguments.callee了。当然此处也可以用func  但是如果是自执行函数,没有func这个变量呢?
    }
    
    AAA() // error:AAA is not defined
    func()
    
    // JS严格模式下,不支持arguments.callee() 
    "use strict"
    (function b(i){
        if(i>=3) return;
        b(++i)  // 这种情况下只能用arguments.callee()  而有了具名化 就可以用具名化的变量了
    })(1)
    
    //匿名函数“具名化”的特点  这个函数名对应的值不可以被修改
    (function b(){
        console.log(b); // function b(){}
        b = 100;
        console.log(b); // function b(){}
    })()
    
    //匿名函数“具名化”的特点  这个函数名对应的值修改的条件是重新声明
    (function b(){
        console.log(b); // undefined
        var b = 100;
        console.log(b); // 100
    })()
    
    (function b(){
        //  注释掉 即可 用let  console.log(b); // 报错 不可以初始化之前访问b
        let b = 100;
        console.log(b); // 100
    })()
    

应用场景

setTimeout(function func(){ // 匿名函数“具名化”
    func()
},1000)