requirejs:为什么模块中定义的函数无法访问require()中的局部变量,我该如何实现呢?

时间:2014-03-07 21:06:36

标签: javascript requirejs

这是我对requirejs的第一次修补,我认为我有一个很好的处理,除了:为什么模块中定义的函数无法访问require()内的局部变量,我怎么能实现这个目标?

如果我们能够专注于这个问题并且 NOT 我使用eval(),更好或替代方法来定义test()或者可能存在的错字,我们将非常感激。下面的代码。

在全局命名空间中给出以下代码:

require(["test"], function(testModule) {
    var test1 = testModule.test1;// same as local test()
    var test2 = testModule.test2; // modified to work as module

    //local function same as testModule.test1
    function test (name, test){
        return test+'='+eval(name+test);
    }

    //define class & instance for testing
    var MyClass1 = function (name) {
        this.name = name;
    };
    var mc1 = new MyClass1('instance 1');
    var objName = 'mc1'

    test(objName, '.name');   // works as expected
    test1(objName, '.name');  // error: mc1 is not defined
    test1.call(this, objName, '.name');  // error: mc1 is not defined
    test2(mc1, objName+'.name');  // works as expected

})

和测试模块定义:

define({
    test1: function (name, test){
        return test+'='+eval(name+test);
    },

    test2: function (obj, test){
        var parts = test.split('.');
        parts[0] = 'obj';
        test = parts.join('.');
        return test+'='+eval(test);
    }
});

问题:

part a)当我调用test1(objName,'。name')时,为什么它没有看到定义为var mc1 = new MyClass1('instance 1')的局部变量?

我知道这是出于好的原因而要保持全局命名空间的清洁,我只是不明白它怎么看不到它。 define()这指向与require()相同的命名空间。

b)如果我想让测试模块访问var mc1,我该怎么办呢?

2 个答案:

答案 0 :(得分:1)

  

当我调用test1(objName,'。name')时,为什么它没有看到定义为var mc1 = new MyClass1('instance 1')的局部变量?

它们在不同的功能中定义。这也是为什么不起作用的原因:

function a() {
   var hello = 'world'
   b()
}

function b() {
   alert(hello)
}

  

如果我想让测试模块访问var mc1,我该怎么办呢?

将定义更改为:

test1: function (name, test, mc1){ ... }

明确传递mc1变量:

test1(objName, '.name', mc1)

这与require.js无关,这是javascript的工作方式。

答案 1 :(得分:1)

如果我们忽略以下代码污染全局namesapce的事实,那么你在做什么在功能上等同于:

// This is the callback you passed to `require`. I've added a
// name to it.
function foo(testModule) {
    var test1 = testModule.test1;// same as local test()
    var test2 = testModule.test2; // modified to work as module

    // ... etc... its all the same as your original code.

    var mc1 = new MyClass1('instance 1');

    // ... etc ...
}

// This is the module `test` that your `require` call was loading.
var test = {
    test1: function (name, test){
        return test+'='+eval(name+test);
    },

    test2: function (obj, test){
        var parts = test.split('.');
        parts[0] = 'obj';
        test = parts.join('.');
        return test+'='+eval(test);
    }
};

// This is what happens when RequireJS executes your module.
foo(test);

我在上面对其进行重组的方式应该明确为什么你不能 访问函数闭包内的任何内容。

至于如何做你想做的事,你可以只将对象引用传递给你的函数。或者,如果您需要一次提供对多个对象的访问,或者想要更改符号所指的内容,则可以传递命名空间:

var ns = {
   mc1:  new MyClass1('instance 1'),
   mc2:  new MyClass1('instance 2'),
   // ...
};

test(ns, "mc1", ...);

这样做,test可以根据需要为mc1分配新值:

function test(ns, name, ...) {
    ns[name] = new MyClass1(...);
}