闭包和解构——解构函数不能互相调用?

Closures & Destructuring — Destructured functions can't call each other?

我有如下内容:

let MM = {
    a: function(){
        b();
    },
    b: function(){
        console.log('b');
    }
};

function makeClosure(M) {
    let { a, b } = M;

    function a2(){ b2() };
    function b2(){ console.log('b2'); };

    return function( arg ){
        if ( arg === 1 ) a();
        if ( arg === 2 ) a2();
    }
}

let c = makeClosure( MM );

////////////////////////////////////////////
// RESULTS

c( 1 ); // b() doesn't exist
c( 2 ); // b2() exists just fine

let MM = {
  a: function(){
    b();
  },
  b: function(){
    console.log('b');
  }
};

function makeClosure(M) {
    let { a, b } = M;

    function a2(){ b2() };
    function b2(){ console.log('b2'); };

    return function( arg ){
        if ( arg === 1 ) a();
        if ( arg === 2 ) a2();
    }
}

let c = makeClosure( MM );

////////////////////////////////////////////
// RESULTS

c( 1 ); // b() doesn't exist
c( 2 ); // b2() exists just fine

为什么会出现以上Results的结果?我认为解构应该等同于声明。为什么解构后的b没有被a找到?它们存在于同一范围内?

有什么方法可以让它工作吗?出于组织原因,我更愿意解构。由于各种原因,我无法将它们保留为方法。

MM.a 的词法范围内没有名为 b 的独立函数,因此从 makeClosure 调用 a() 会导致错误,因为没有名为 b 的变量或函数b 可以在 MM 中的 a 函数中找到。

一种可能性是传递 a 函数来执行,这样 MM 不依赖于任何外部变量:

let MM = {
    a: function(someFn){
        someFn();
    },
    b: function(){
        console.log('b');
    }
};

function makeClosure(M) {
    let { a, b } = M;

    function a2(){ b2() };
    function b2(){ console.log('b2'); };

    return function( arg ){
        if ( arg === 1 ) a(b);
        if ( arg === 2 ) a2();
    }
}

let c = makeClosure( MM );
c(1);
c(2);

另一种选择是 makeClosure 中的 call a 具有具有 b 属性 的对象的调用上下文,就像 MM,并让 MM.a 调用 this.b:

let MM = {
    a: function(){
        this.b();
    },
    b: function(){
        console.log('b');
    }
};

function makeClosure(M) {
    let { a, b } = M;

    function a2(){ b2() };
    function b2(){ console.log('b2'); };

    return function( arg ){
        if ( arg === 1 ) a.call({ b });
        if ( arg === 2 ) a2();
    }
}

let c = makeClosure( MM );
c(1);
c(2);

这个问题与解构没有任何关系 - 它只是普通的 JS 作用域规则。