对 类 和 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 子类定义。
我已经花了 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 子类定义。