JavaScript装饰模式.错误:超出了最大调用堆栈大小

Y B*_*ond 7 javascript recursion decorator

这是Decorator模式的一个工作示例:

class Dummy {
    run() {
        console.log('run');
    }
}

function get() {
    let instance = new Dummy();
    instance.run = ((func) => {
        return function() {
            func();
            console.log('decorator run');    
        }
    })(instance.run);

    return instance;
}

let obj = get();
obj.run();
Run Code Online (Sandbox Code Playgroud)

但是,如果我们将get函数更改为:

function get() {
    let instance = new Dummy();
    instance.run = function() {
        instance.run();
        console.log('decorator run');  
    }       

    return instance;
}
Run Code Online (Sandbox Code Playgroud)

我们将面临一个错误: VM68418:6 Uncaught RangeError:Dummy.instance.run(:6:32)超出了最大调用堆栈大小

为什么会这样?所述instance.run仍然是围绕原始方法的包装,而不"无用"附加的自执行的功能.

我很高兴听到答案

geo*_*org 2

在第一个示例中, 的当前值instance.run保留在func关闭变量中,然后instance.run分配一个新值::

instance.run = <old function>
func = instance.run
instance.run = <new function>
// func === <old function> here
Run Code Online (Sandbox Code Playgroud)

因此,当instance.run调用时func,它本质上是调用<old function>

您可以在不使用 IIFE 的情况下执行相同的操作,只需funcget():

instance.run = <old function>
func = instance.run
instance.run = <new function>
// func === <old function> here
Run Code Online (Sandbox Code Playgroud)

在第二个片段中,instance.run旧值丢失,并且它有效地调用自身,导致堆栈溢出。