我需要实现类似ODM的小功能。我从数据库中得到了一个简单的javascript对象,我需要将它转换为我的模型类实例。让我们假设模型看起来像:
class Model{
constructor(){
this.a = '777';
---- whole bunch of other things ---
}
print(){
console.log(this.a);
}
}
所以我需要将var a = {b:999, c:666}
转换为模型的实例,然后能够调用a.print()
,当a.print()
执行777
时,应该将其放在控制台中。如何做到这一点?
有一个简单的方法。只需将对象分配给实例(此)
class Model
{
constructor(obj){
Object.assign(this, obj)
}
print(){
console.log(this.a);
}
}
let obj = {a: 'a', b: 'b', c: 'c'}
let m = new Model(obj)
console.log(m)
m.print() // 'a'
如果我正确理解这个问题,你可以导出一个工厂函数,并使用Object.assign
来扩展你的基础Model
:
// Export the factory function for creating Model instances
export default const createModel = function createModel(a) {
const model = new Model();
return Object.assign(model, a);
};
// Define your base class
class Model {
constructor() {
this.a = 777;
}
print() {
console.log(this.a, this.b, this.c)
}
}
并称之为:
const myModel = createModel({ b: 999, c: 666 });
myModel.print();
Babel REPL示例
当然,也可以放弃工厂,将a
作为参数(或rest参数)传递给构造函数,但这取决于您喜欢的编码风格。
如果您需要更一致的类型转换,您也可以创建自己的typecast
函数,如泛型函数
function typecast(Class, obj) {
let t = new Class()
return Object.assign(t,obj)
}
// arbitrary class
class Person {
constructor(name,age) {
this.name = name
this.age = age
}
print() {
console.log(this.name,this.age)
}
}
调用它将任何对象类型转换为任何类实例,如
let person = typecast(Person,{name:'Something',age:20})
person.print() // Something 20
我建议重写您的类,将其所有属性存储在单个JS对象this.props
中,并在其构造函数中接受此对象:
class Model {
constructor (props = this.initProps()) {
this.props = props
// other stuff
}
initProps () {
return {a: '777'}
}
print () {
console.log(this.props.a)
}
}
然后,您可以将this.props
作为一个普通的JS对象存储在数据库中,然后使用它轻松地重新创建相应的类实例:
new Model(propsFromDatabase)
不过,如果您不想将所有属性移动到this.props
,您可以使用Object.assign
来保持对象的简洁:
class Model {
constructor (props = this.initProps()) {
Object.assign(this, props)
// other stuff
}
initProps () {
return {a: '777'}
}
print () {
console.log(this.a)
}
}
但我建议使用前一种方法,因为它可以防止名称冲突。
这个怎么样?:
var a = Object.create(Model.prototype, {
b: {
enumerable: true, // makes it visible for Object.keys()
writable: true, // makes the property writable
value: 999
}, c: {
value: 666
}
});
基本上,您将从Model的原型创建一个新的Model实例,并将您的新属性分配给它。您还应该能够调用print
。
您可以有一个静态Model.from
或Model.parse
方法,它返回一个具有以下属性的新Model:
class Model {
static defaults = { a: 777, b: 888, c: 999, d: 111, e: 222 };
constructor() {
const { defaults } = Model;
for (const key in defaults) this[key] = defaults[key];
}
print() {
console.log(this.a);
}
static from(data) {
const { defaults } = Model;
return Object.assign(
new Model(),
defaults,
Object.fromEntries(
Object.entries(data).filter(([key]) => key in defaults)
)
);
}
}
const data = {
a: "a", b: "b", c: "c", ajkls: "this wont be included"
};
const myModel = Model.from(data);
console.log("myModel =", myModel);
console.log("myModel instanceof Model:", myModel instanceof Model);
console.log("myModel.print():")
myModel.print();
就像G_hi3的答案一样,但它"自动"创建属性对象
function Model() {
this.a = '777';
}
Model.prototype.print = function(){
console.log(this.a);
}
// Customize this if you don't want the default settings on the properties object.
function makePropertiesObj(obj) {
return Object.keys(obj).reduce(function(propertiesObj, currentKey){
propertiesObj[currentKey] = {value: obj[currentKey]};
return propertiesObj;
}, {}); // The object passed in is the propertiesObj in the callback
}
var data = {a: '888'};
var modelInstance = Object.create(Model.prototype, makePropertiesObj(data));
// If you have some non trivial initialization, you would need to call the constructor.
Model.call(modelInstance);
modelInstance.print(); // 888
首先声明要在其中转换JSON:的class
class LoginResponse {
constructor(obj) {
Object.assign(this, obj);
}
access_token;
token_type;
expires_in;
}
现在将通用javascript对象转换为您想要的类对象:
const obj = {
access_token: 'This is access token1',
token_type: 'Bearer1',
expires_in: 123,
};
let desiredObject = new LoginResponse(obj);
console.log(desiredObject);
输出为:
LOG {"access_token": "This is access token1", "expires_in": 123, "token_type": "Bearer1"}