如何从另一个函数内部执行的函数内部访问变量?

时间:2018-12-12 11:39:39

标签: javascript function closures

我正在重构我的https://github.com/perdugames/cacau测试库,我这样做是为了进一步了解JavaScript和测试。问题是我不喜欢FIXTURE当前的工作方式,所以我决定进行重构,我想在下面获得结果,但是我仍然不知道如何使“ addTest”函数可以访问“ x“。

const runner = new Runner();

runner.addSuite(() => {
    console.log('Suite 1');

    runner.addFixture(() => {
        console.log('Suite');
        const x = 10;
    });


    runner.addTest(() => {
        console.log('Test 1');
        console.log(x);
    });

    runner.addTest(() => {
        console.log('Test 2');
        console.log(x);
    });

});

runner.run();

注意:当然,不使用全局变量,也不添加“运行器”的范围。

3 个答案:

答案 0 :(得分:2)

实际上,您应该使用上下文。请阅读更多有关javascript上下文的信息。有很多网站。

根据您的情况,您可以调用上下文

obj.funcA(() => {
    let ctx = this;
    console.log('A');

    obj.funcA1(() => {
        let ctxFncA1 = this // context of previous level... etc.
        console.log('A1');
        const x = 10;
    });

    // ... you get the point.    
});

通常,您要尝试执行的操作不是“确定”。如果您要构建对象类,则JavaScript语言可能允许您执行任何操作,但您不能这样做。

可能您应该研究JavaScript(书籍或培训网站)中的对象编程。

实际上,您有一个描述所需内容的示例:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let(从此处复制/粘贴代码。)

var Thing;

{
  let privateScope = new WeakMap();
  let counter = 0;

  Thing = function() {
    this.someProperty = 'foo';

    privateScope.set(this, {
      hidden: ++counter,
    });
  };

  Thing.prototype.showPublic = function() {
    return this.someProperty;
  };

  Thing.prototype.showPrivate = function() {
    return privateScope.get(this).hidden;
  };
}

console.log(typeof privateScope);
// "undefined"

var thing = new Thing();

console.log(thing);
// Thing {someProperty: "foo"}

thing.showPublic();
// "foo"

thing.showPrivate();
// 1

答案 1 :(得分:0)

我不认为这在物理上是可能的。如果您不想使用全局变量,或者必须在类或对象的范围内对其进行访问,则必须将变量传递给函数才能访问它。

尽管此变量应该在您的堆中,但是如果不向指针或值本身传递任何东西,则无法将其地址传递给新函数的范围。

答案 2 :(得分:0)

我发现了两种解决问题的方法,第一种是:

function test(){  
    console.log(this.x * 2);
}
function fixture() {
    this.x = 5;
}
test.call(new fixture()) // 10

这是我发现的最糟糕的方法,因为我将始终不得不使用“ this”,并且我仍然必须将FIXTURE作为构造函数处理,否则在这种情况下使用文字对象会更好。

我选择的第二种方法更简单,并且已经可以满足我的准备要求:

const runner = new Runner();

runner.addSuite(() => {
    console.log('Suite 1');
    var x;
    runner.addFixture(() => {
        console.log('Suite');
        x = 1;
        x++;
    });
    runner.addTest(() => {
        console.log('Test 1');
        console.log(x); // 2
    });

    runner.addTest(() => {
        console.log('Test 2');
        console.log(x); // 2
    });

});