对 类 和 JavaScript 模块使用反射

Using Reflection with Classes and JavaScript Modules

我已经花了 8 个多小时对此进行修补,希望得到一些建议。我的 objective 是在将来的某个时候实施最有可能原生于 JavaScript 的方法。我希望该解决方案能够在 Web 浏览器和节点服务器上运行。既然如此,我想尽可能避免香草以外的任何东西JavaScript。

这是我的困境。我有两个 classes,每个都在自己的文件中。我的问题显示在 Model class 的 get() 方法中。

ChildModel.js

import Model from './Model.js';

class ChildModel extends Model {

    // Data which describes where data is stored on the server
    static meta = {
        url: 'api/child-model/';
    }

}

export default = ChildModel;

Model.js

class Model {

    // A convenient method which all models use to get their data from the server
    async get() {
        // Use reflection to get the name of the extended child class
        var modelClassName = this.name; // "ChildModel"

        // Nice, now I know the name of my class
        // Now, I just need to get to the actual class definition so I can access the static .meta property
        // I have three options that I can think of to do this:

        // Option 1 - Use a global
        var ModelClass = window[modelClassName]; // or global[modelClassName]
        // Pros: looks straightforward
        // Cons: pollutes the global namespace and requires me to write 
        // nasty code to put all of my models onto window or global.
        // Does not work because inside module there is no access to window or global

        // Option 2 - Use require()
        var ModelClass = require('./models/'+modelClassName+'.js');
        // Pros: works perfectly on server side in Node
        // Cons: does not work at all in the browser without third party software

        // Option 3 - Use import()
        var importedModelClass = await import('./models/'+modelClassName+'.js');
        var ModelClass = importedModelClass.default;
        // This is basically the same as Option 2

        // Option 4 - ???
    }

}

export default = Model;

为了暂时解决这个问题,我目前正在使用 Rollup to put all of my files into a single index.js file. I am then using a dynamic import plugin 来实施选项 #3。它有效,但我整天坐在这里结束编码,认为这不是 2020 年做事的最佳方式。我是不是错过了一些明显的东西,还是这是这样做的?

您可以改为这样做:

class Model {

    // A convenient method which all models use to get their data from the server
    async get(meta) {
       // static meta value
       console.log(meta)
    }

}

class ChildModel extends Model {

    // Data which describes where data is stored on the server
    meta = {
        url: 'api/child-model/',
    }

    getWithMeta = () => this.get(this.meta)

}

const foo = new ChildModel();
foo.get(); // undefined
foo.getWithMeta(); // { url:"api/child-model/" }

但是您会失去静态值。它们用于无论如何在没有 class 实例化的情况下调用的方法,而不是真正用于 class 方法

中的属性访问

此外,here 是在浏览器上导入文件的技巧,node.js

mymodule.js

(function(exports){

    // your code goes here

   exports.test = function(){
        return 'hello world'
    };

})(typeof exports === 'undefined'? this['mymodule']={}: exports);

node

var mymodule = require('./mymodule'),
    sys = require('sys');

sys.puts(mymodule.test()); 

browser

<script src="mymodule.js"></script> 
<script>
    alert(mymodule.test());
</script> 

事实证明,您可以在静态方法中引用 this,它将 return 子类定义。