简体   繁体   English

对类和 JavaScript 模块使用反射

[英]Using Reflection with Classes and JavaScript Modules

I'm at the point where I've spent over 8 hours tinkering with this and would love some advice.我已经花了 8 多个小时来修补这个问题,并且希望得到一些建议。 My objective is to implement the approach which is most likely to be native to JavaScript at some point in the future.我的目标是在未来的某个时候实施最有可能成为 JavaScript 原生的方法。 I want the solution to work both in web browsers and on a Node server.我希望该解决方案在 web 浏览器和节点服务器上都可以工作。 That being the case, I want to avoid anything besides vanilla JavaScript as much as possible.既然如此,我想尽可能避免除了香草 JavaScript 之外的任何东西。

Here is my dilemma.这是我的困境。 I have two classes, each in their own file.我有两个类,每个类都在自己的文件中。 My problem is shown in the get() method of the Model class.我的问题显示在Model class 的get()方法中。

ChildModel.js 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 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;

To solve the issue for now, I'm currently using Rollup to put all of my files into a single index.js file.为了暂时解决这个问题,我目前正在使用Rollup将我的所有文件放入一个 index.js 文件中。 I am then using a dynamic import plugin to implement option #3.然后我使用动态导入插件来实现选项#3。 It works, but I am sitting here at the end of coding all day and thinking this can't be the best way to do things in 2020. Did I miss something obvious or is this how it's done?它可以工作,但是我整天都坐在这里编码结束,并认为这不是 2020 年做事的最佳方式。我错过了一些明显的事情还是它是这样完成的?

You could do something like this instead:你可以这样做:

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/" }

But you would lose the static value.但是您会丢失 static 值。 They are used for methods anyways to be called without class instantiation, not really for an attribute access in class methods它们用于在没有 class 实例化的情况下调用的方法,而不是真正用于 class 方法中的属性访问

Also here is a trick to import files on browser and node.js这里还有一个在浏览器和 node.js 上导入文件的技巧

mymodule.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>

Turns out you can just reference this inside of a static method and it will return the subclass definition.原来你可以在 static 方法中引用this ,它会返回子类定义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM