如何将同一闭包下的对象分离到不同的文件中

发布于 2024-09-14 04:27:01 字数 1577 浏览 3 评论 0原文

我为我的客户提供了以下结构;

var myObject = (function(){
    var mainObjectList = [];
    var globalObject = {
            init:function(mainObjectId){
                var logger = {};
                var utilityObject1 = {};
                var utilityObject2 = {};
                var mainObject = {};
                mainObjectList.push(mainObject);
            },//init
            someOtherMethods:function(){}
        };//globalObject
    return globalObject;
})();

我可以对我的客户说 myObject.init(5); 并创建一个新的结构。 我的问题是我在 init 函数闭包中有很多实用程序对象(logger、utilityObject1、utilityObject2..)。我的总文件超过 1000 行,因此我想将所有实用程序对象分成不同的文件,以获得更好的项目。例如,我可以将 logger、utilityObject1、utilityObject2 分离到它们自己的文件中。问题是由于对象处于关闭状态,我不能将它们添加到单独文件中的主对象中。于是我想到了下面的注入方法。

//start of file1
var myObject = (function(){
    var mainObjectList = [];
    var globalObject = {
            init:function(mainObjectId){
                var logger;
                var utilityObject1 = {};
                var utilityObject2 = {};
                var mainObject = {};
                mainObjectList.push(mainObject);
            },//init
            someOtherMethods:function(){},
            injectLogger:function(creator){
                this.logger = creator();
            }
        };//globalObject
    return globalObject;
})();
//start of file2
myObject.injectLogger(function(){return {};});

这样我就可以分离我的文件进行开发。但在生产中我可以将文件连接成一个文件。但我对这个设计有一些问题。我刚刚在 myObject 中添加了一个可访问的jectLogger 函数。我的记录器现在不能在闭包中使用其他局部变量(我现在必须将它们传递给创建者对象)。我的问题是有没有其他方法可以将此类代码分离到文件中。 (也许是外部实用程序。)

I have following structure for my client;

var myObject = (function(){
    var mainObjectList = [];
    var globalObject = {
            init:function(mainObjectId){
                var logger = {};
                var utilityObject1 = {};
                var utilityObject2 = {};
                var mainObject = {};
                mainObjectList.push(mainObject);
            },//init
            someOtherMethods:function(){}
        };//globalObject
    return globalObject;
})();

with my client I can say
myObject.init(5);
and create a new structure.
My problem is I have a lot of utility objects inside init function closure (logger, utilityObject1, utilityObject2..). My total file exceeded 1000 lines so I want to separate all utility objects into different files to have a better project. for example I could separate logger, utilityObject1 , utilityObject2 to their own files. the problem is since objects are in closure I cannot just add them to main object in separate files. so I thought of following injection method.

//start of file1
var myObject = (function(){
    var mainObjectList = [];
    var globalObject = {
            init:function(mainObjectId){
                var logger;
                var utilityObject1 = {};
                var utilityObject2 = {};
                var mainObject = {};
                mainObjectList.push(mainObject);
            },//init
            someOtherMethods:function(){},
            injectLogger:function(creator){
                this.logger = creator();
            }
        };//globalObject
    return globalObject;
})();
//start of file2
myObject.injectLogger(function(){return {};});

That way I can separate my files for development. but in production I can concatenate files to have one file. But I have some problems with this design. I just added an accessible injectLogger function into myObject. and my logger cannot use other local variables in closure now(I have to pass them to creator object now). My question is is there any other way to separate that kind of code into files. (maybe an external utility.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

迷你仙 2024-09-21 04:27:01

我喜欢使用google的闭包编译器http://code.google.com/closure/compiler/

如果你不想使用类似的东西,你可以尝试这样的事情:(确保你首先加载 globalObject.js 来定义变量)。

//globalObject.js
var globalObject = function() {

}

//init.js
globalObject.prototype.init = function() {
    this.utilityFunction();
    //do something with utilityObject1
    this.utilityFunction(this.utilityObject1);
}

//utilityFunction.js
globalObject.prototype.utilityFunction= function() {}

//utilityObject1.js
globalObject.prototype.utilityObject1 = {};

//main.js
var myObject = new globalObject();
myObject.init();

然后您可以通过执行以下操作来覆盖该函数:

//main.js
var myObject = new globalObject();
myObject.utilityFunction = function() {
    //new function
}
myObject.init(); // This will then use the new utilityFunction method you just set.

I like to use google's closure compiler http://code.google.com/closure/compiler/

If you don't want to use something like that, you might try this sort of thing: (Make sure you load globalObject.js first to define the variable).

//globalObject.js
var globalObject = function() {

}

//init.js
globalObject.prototype.init = function() {
    this.utilityFunction();
    //do something with utilityObject1
    this.utilityFunction(this.utilityObject1);
}

//utilityFunction.js
globalObject.prototype.utilityFunction= function() {}

//utilityObject1.js
globalObject.prototype.utilityObject1 = {};

//main.js
var myObject = new globalObject();
myObject.init();

You could then overwrite the function by doing something like this:

//main.js
var myObject = new globalObject();
myObject.utilityFunction = function() {
    //new function
}
myObject.init(); // This will then use the new utilityFunction method you just set.
眼眸 2024-09-21 04:27:01

据我了解,您希望拥有一些所有模块都关闭的词法变量,但您希望将各个模块的代码保留在不同的文件中。

实现这种精确行为的一种方法是通过将模块定义连接在一起来创建单个 Javascript 文件:

Header.js-partial

var myObject = (function(){
    var mainObjectList = [];
    var globalObject = {
            init:function(mainObjectId){

Logger.js:

function Logger() { this.enabled = true; }
Logger.prototype.log = function() {
  if (window.console && window.console.log) {
     return window.console.log.apply(window.console.log, arguments]);
  }
}

等。

根据需要添加其他模块文件。它们可以引用词汇变量。

Footer.js-部分

    }// end init
}; // end globalObject
return globalObject;

})();

最后,您需要一个脚本将所有这些文件连接到一个 js 文件中。没有其他方法可以在纯 Javascript 中获得真正的词法变量访问。

更好的替代方案

也就是说,这种技术很容易造成混乱,我不推荐它。闭包通常用于关闭局部变量,而不是程序范围的变量。如果您使用 1000 行前声明的词法变量,您将花费一些时间来跟踪运行程序时声明所有变量的位置。相反,您可能应该将私有的“全局”数据包含在 globalObject 中。例如,将 mainObjectList 存储在 globalObject.mainObjectList 中,并在模块文件中引用它。

我推荐像 nemophrost 描述的解决方案。每个文件本身都应该是有效的 javascript。

As I understand it, you want to have some lexical variables that all of your modules close over, but you want to keep the code for the various modules in different files.

One way to achieve this exact behavior is to create a single Javascript file by concatenating the module definitions together:

Header.js-partial

var myObject = (function(){
    var mainObjectList = [];
    var globalObject = {
            init:function(mainObjectId){

Logger.js:

function Logger() { this.enabled = true; }
Logger.prototype.log = function() {
  if (window.console && window.console.log) {
     return window.console.log.apply(window.console.log, arguments]);
  }
}

etc.

Add other module files as desired. They can reference lexical variables.

Footer.js-partial

    }// end init
}; // end globalObject
return globalObject;

})();

In the end you need a script that will concatenate all of these files together into a single js file. There is no other way to get truly lexical variable access in pure Javascript.

A superior alternative

That said, this technique is ripe for confusion and I don't recommend it. Closures are generally meant for closing over local variables, not program-wide variables. If you use a lexical variables declared 1000 lines ago, you will spend some amount of time tracking down where all your variables were declared when running your program. Instead you should probably enclose private, 'global' data in the globalObject. For example, store mainObjectList in globalObject.mainObjectList and reference that in module files.

I recommend a solution like that described by nemophrost. Each file should be valid javascript on its own.

紫竹語嫣☆ 2024-09-21 04:27:01

您可以使用命令行 PHP 作为预处理器来合并文件。例如,main.js.php 可能如下所示:

(function() {
    <?php require('foo.js.php');?>
})();

然后运行命令 php main.js.php > merged.js 当您想要生成可用于缩小和部署的输出文件时。

这样做的优点是您可以将 main.js.php 加载到服务器上来测试新版本的代码而无需重新编译。您只需在 main.js.php 的开头添加一行即可让 PHP 发送正确的 MIME 类型:

<?php header('Content-type: text/javascript');?>

You could use command-line PHP to serve as a preprocessor to combine your files. For example, main.js.php could look like this:

(function() {
    <?php require('foo.js.php');?>
})();

and then run the command php main.js.php > combined.js when you want to produce an output file usable for minification and deployment.

This has the advantage that you can load main.js.php onto a server to test a new version of the code without recompiling. You can just put a line at the very beginning of main.js.php to get PHP to send the correct MIME type:

<?php header('Content-type: text/javascript');?>
最美不过初阳 2024-09-21 04:27:01

我处理这个问题的方法是检查全局对象是否存在,如果不存在则创建它。这样顺序就不重要了。

// file 1
var Global_Obj = Global_Obj || {};  // creates empty global object
Global_Obj.An_Obj = { /* stuff */ };

// file 2
var Global_Obj = Global_Obj || {}; // uses created global object
Global_Obj.Another_Obj = { /* stuff */ };

The way I deal with this problem to check to see if the global object exists and if not create it. This way the order isn't important.

// file 1
var Global_Obj = Global_Obj || {};  // creates empty global object
Global_Obj.An_Obj = { /* stuff */ };

// file 2
var Global_Obj = Global_Obj || {}; // uses created global object
Global_Obj.Another_Obj = { /* stuff */ };
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文