【问题标题】:Add variable to a functions scope / closure. function equivalent of window object将变量添加到函数范围/闭包。窗口对象的等效函数
【发布时间】:2014-07-28 15:57:00
【问题描述】:

通过以下代码,我可以从对象中取出值并将它们添加到全局命名空间中。这是在暴露函数中定义的

function expose(key, obj){
  window[key] = obj[key];
}

我可以一直用它来从库中获取我经常使用的功能,例如下划线的地图

// before
map               //undefined
_.map             // have to use like this

expose('map', _)

// after
map // function

我想修改暴露,以便它完成相同的工作,但仅在闭包中。如何解决这个问题是我想表达的问题。

map //undefined

(function(){
expose('map', {})

// map can be used here 
}())
// map is still undefined here.

我知道在这种情况下这个问题可以通过var map = _.map 来解决,我在这里提供一个简化版本来描述这一点。我想如上所述解决它,我可以编写一个一次公开多个变量的函数。

对于一个复杂的例子,看看这个 repo。

https://github.com/CrowdHailer/cuminjs

expose 函数的测试在这里找到

https://github.com/CrowdHailer/cuminjs/blob/master/spec/cumin_spec.js

更好地表达我想要的最终结果的大型示例

// file one - sets up some core utilities
var MyModule = (function(){
var foo = function(){
  // ..some functionality
};

return {
  foo: foo
  // plus several more functions
};
}());


// file two - sets up some other functionality.
// Makes use of lots of the functions set up in file 1
(function(parent){
  // var foo = MyModule.foo -trying to avoid as want to use several maybe names change

  expose([foo, etc], MyModule);

  var bar = function(){
    // .. other code would like to make use of foo
  };

  parent.extend({
    bar: bar
  });
}(MyModule))

【问题讨论】:

  • 只是好奇你是否尝试做类似 RequireJS (requirejs.org) 的事情?
  • 我对 requirejs 没有太多经验。然而,快速阅读接缝可能是类似的事情。 require 是否允许您将项目要求到闭包中?
  • 它更像是一个模块加载器。但是是的,它允许您定义模块(作为闭包),然后在代码中的其他地方“要求”它们作为依赖项。
  • 是否可以创建自定义对象并将外部库方法分配为该对象的方法? (例如在你的闭包中使用 my.map(thing) 而不是 map(thing) )如果不是,我看不到不使用 eval 的方法。

标签: javascript function scope closures


【解决方案1】:

我知道在这种情况下这个问题可以通过var map = _.map 解决。

这正是(唯一)要走的路。

我想写一个函数,一次暴露多个变量。

你不应该。看看我对双重问题的回答Is it possible to import variables in JavaScript (node.js)?

但是,exporting 变量(进入您不拥有的范围)甚至比 importing(进入您自己的范围)更复杂。基本上,这是不可能的,因为作用域(除了global)不是可以传递和动态修改的对象。

如何解决这个问题

您需要修改要更改/扩展其范围的函数的代码。我可以想到两种方法:

  • 使用evalexport() 将返回一个声明和初始化变量的语句:

    function export() {
        var lines = [];
        for (var p in moduletoexpose)
            lines.push("var "+p+" = require('moduletoexpose')."+p+";");
        return lines.join("\n");
    }
    
    (function() {
        eval(export(…));
        // use `map` here
    }())
    
  • 类似地,您可以编写一个函数来获取闭包,对其进行反编译,将变量声明添加到代码中,然后使用Function 构造函数从中创建一个函数。它可能被用作

    exportTo(…, function() {
        // use `map` here
        // don't use any free variables but global ones
    })();
    

    听起来不如eval 解决方案好,但您可能想查看this answer 以获取有关如何编写这样一个exportTo 的灵感。

【讨论】:

  • 这看起来有我要找的东西。我听说 eval 是要避免的。我将尝试编写一个更好的示例,说明我试图通过分解闭包来创建具有污染全局命名空间的大型功能一次。
  • 是的,eval 是要避免,但这是实现您想要的唯一方法。正如我所建议的那样,您当然可能希望完全避免export()ing(请参阅有关导入变量的链接)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-19
  • 2012-06-06
  • 1970-01-01
相关资源
最近更新 更多