使用动态函数调用创建 JS 库

Creating JS library with dynamic function calling

本文关键字:JS 创建 函数调用 动态      更新时间:2023-09-26

我正在创建一个JS'库'文件,但我想将其完整封装在一个对象中,以避免污染包含该文件的页面的命名空间

这样做的转折点是在库内的函数中,我需要按名称调用库中的其他函数,例如使用 window[]

下面的代码只是一个示例,实际上有数百个函数可以按名称调用。这是由麻烦引起的,因为我无法window[]引用该函数,正确的方法是什么?

我已经在主机页面中尝试过这个:

<script src= "mylib.js"></script>
var oMyLib = new cMyLib(); //there will only ever be one 'instance' of this

在 mylib 中.js所有内容都包含在一个函数中:

function cMyLib() {
    this.doStuff = function () {
        someFunc(this);  //call another function in the lib
    }
    //    I tried it with prototypes also
    //    cMyLib.prototype.doStuff = function () {
    //        someFunc();
    //    }

    function someFunc(that) {
      var s='anotherFunc1'
      var f = window[s];   //undefined!
      f();
      s='anotherFunc2'
      f=window[s];
      f();
    }
    function anotherFunc1() {}
    function anotherFunc2() {}
}

您要按名称(或实际上按数字,根据您的注释)引用的函数应该是该对象的一部分,而不是通过window访问,例如:

function cMyLib() {
    // allow call without new
    if (! (this instanceof cMyLib)) {
        return new cMyLib();
    }
    // enforce singleton
    if (this.constructor.singleton) {
        return this.constructor.singleton;
    } else {
        Object.defineProperty(this.constructor, 'singleton', {
            value: this
        });
    }
    // instruction array (no need to expose via `this`)
    var insn = [];
    insn[0x4c] = function lda_immediate() { ... }
    // instruction execution
    this.step = function() {
        var opcode = memory[pc++];
        if (opcode in insn) {
            // `.call` ensures `this` is set inside the instruction fn.
            insn[opcode].call(this);
        } else {
            hcf();
        }
    }
}

请注意顶部的额外内容 - 方便代码,以确保只能存在一个cMyLib

只要函数在父作用域中,您就可以直接引用它,即

function someFunc(that) {
    anotherFunc1();
};

将简单地工作。

另一件事是,这样做的经典方法是将所有内容包装在一个自调用匿名函数中,即

(function() {
    function anotherFunc1() {};
    function anotherFunc2() {};
    this.cMyLib = function() { ... };
})();

但是你的方法也很好。

如果您希望通过动态名称调用函数,则可以将它们存储在顶级对象中:

(function() {
    var my_functions = {
        anotherFunc1: function() {},
        anotherFunc2: function() {}
    };
    this.cMyLib = function() {
        var name = 'anotherFunc1';
        my_functions[name]();
    };
})();

这就像创建一个孤立的"全局"范围。

旁注:请勿使用 eval .这是非常不安全和缓慢的。它会在某个时候适得其反。