Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/374.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript:如何向属于类的类对象添加属性?_Javascript_Node.js_Typescript_Ecmascript 6 - Fatal编程技术网

Javascript:如何向属于类的类对象添加属性?

Javascript:如何向属于类的类对象添加属性?,javascript,node.js,typescript,ecmascript-6,Javascript,Node.js,Typescript,Ecmascript 6,我一直在考虑是否可以做到这一点。如果是,如何进行?我对javaScript世界还相当陌生,所以请容忍我 为了更好地解释我想要实现的目标,我将提供一个小例子: 如您所见,Document类只有一个名为basicDetails的属性。但是它的构造函数接受的objDocument不仅有基本的细节对象,还有其他属性 let obj = {basicDetails: {type: "draft"}, lineDetails:{lineid:123,itemName:"ite

我一直在考虑是否可以做到这一点。如果是,如何进行?我对javaScript世界还相当陌生,所以请容忍我

为了更好地解释我想要实现的目标,我将提供一个小例子:

如您所见,Document类只有一个名为basicDetails的属性。但是它的构造函数接受的
objDocument
不仅有基本的细节对象,还有其他属性

let obj = {basicDetails: {type: "draft"}, lineDetails:{lineid:123,itemName:"itemName"} }
 let doc = new Document(obj)
 console.log(doc)
上述代码的输出自然为:

  {
  "basicDetails": {
    "type": "",
    "createdDate": "2020-12-03T08:02:59.780Z"
  }
} 
  {
  "basicDetails": {
    "type": "",
    "createdDate": "2020-12-03T08:02:59.780Z"
  },
   "lineDetails":{"lineid":123,"itemName":"itemName"} }
} 
但我希望输出为:

  {
  "basicDetails": {
    "type": "",
    "createdDate": "2020-12-03T08:02:59.780Z"
  }
} 
  {
  "basicDetails": {
    "type": "",
    "createdDate": "2020-12-03T08:02:59.780Z"
  },
   "lineDetails":{"lineid":123,"itemName":"itemName"} }
} 
属于
objDocument的任何属性:除了基本细节之外的任何
都必须按原样自动添加。并且属性不应该被添加到类的外面

let doc = new Document(obj)
doc["lineDetails] = obj.lineDetials // not acceptable

您可以从传递给文档构造函数的对象中提取基本细节,并使用带扩展语法的解构来识别其余的内容

在这个演示中,我注释掉了typescript部分,因此它可以在这里运行:

类文档{
基本细节/*:基本细节*;
构造函数(objDocument/*:any*/){
设{basicDetails,…rest}=objDocument;
this.basicDetails=新的basicDetails(basicDetails);
对象。分配(此,其余);
}
}
类基本细节{
type/*:字符串*/;
createdDate/*:日期*;
构造函数(objDocument/*:any*/){
this.type=objDocument.type;
this.createdDate=新日期();
}
}
设obj={basicDetails:{type:“draft”},lineDetails:{lineid:123,itemName:“itemName”};
let doc=新文档(obj);

控制台日志(doc)首先,您可以通过提取
文档的构造函数选项来简化您的生活。由于您需要根级别的
basicDetails
,然后可能需要其他任何内容,因此:

接口文档选项{
基本细节:任何,
[键:字符串]:未知
}
这意味着您至少可以获得某种类型安全性,并防止在没有
基本细节的情况下实例化
文档

现在,您可以将构造函数更改为提取
basicDetails
,以实例化
basicDetails
对象,然后将所有其他内容分配给当前实例。为
文档
提供[索引签名]意味着它可以具有任意数量的任何属性。将这些属性设置为只读意味着不允许更改它们:

类文档{
基本细节:基本细节;
只读[键:字符串]:未知
构造函数({basicDetails,…otherDetails}:DocumentOptions){
this.basicDetails=新的basicDetails(basicDetails);
分配(此、其他详细信息);
}
}
通过为
BasicDetails
的构造函数指定正确的类型,然后使用[
ConstructorParameters
]实用程序类型来确保将正确的内容传递给
文档,可以进一步提高类型安全性:

接口文档选项{
基本细节:构造函数参数[0],
[键:字符串]:未知
}
类文档{
基本细节:基本细节;
只读[键:字符串]:未知
构造函数({basicDetails,…otherDetails}:DocumentOptions){
this.basicDetails=新的basicDetails(basicDetails);
分配(此、其他详细信息);
}
}
类基本细节{
类型:字符串;
createdDate:日期;
构造函数(对象文档:{}){
this.type=“”;
this.createdDate=新日期();
}
}
设obj={basicDetails:{type:“draft”},lineDetails:{lineid:123,itemName:“itemName”}
let doc=新文档(obj)
doc[“lineDetails”]=obj.lineDetials//不可接受
控制台日志(doc)
如果您想更能经得起未来的考验,那么您可以接受
基本细节
的整个参数列表,因此如果构造函数将来发生更改,您不需要更改
文档
文档选项

interface DocumentOptions {
    basicDetails: ConstructorParameters<typeof BasicDetails>, //no index
    [key: string]: unknown
}

class Document {
    basicDetails: BasicDetails;
    readonly [key: string]: unknown
    constructor({ basicDetails, ...otherDetails } : DocumentOptions) {
        this.basicDetails = new BasicDetails(...basicDetails);
//pass everything                            ^^^
        Object.assign(this, otherDetails);
    }
}
为了方便起见,我添加了一个
serialise
方法-它将按照您的期望输出信息:

{
“基本细节”:{
“类型”:“,
“createdDate”:“2020-12-03T09:09:30.355Z”
},
“线路详细信息”:{
“lineid”:123,
“项目名称”:“项目名称”
}
} 
它还提供免费克隆功能,因为它输出的数据与构造函数使用的数据完全相同,所以您可以执行以下操作:

let obj={basicDetails:{type:“draft”},lineDetails:{lineid:123,itemName:“itemName”}
let doc1=新文档(obj)
//自由克隆
让doc2=新文档(doc1.serialise());

这是对@trincot answer的改进。首先,设计不是最好的,应该将已经创建的类注入到文档构造函数中

class Document {
    basicDetails /*: BasicDetails */;
    constructor(basicDetails /*:BasicDetails*/, rest : /*:any*/) {
       this.basicDetails = basicDetails
       Object.assign(this, rest);
    }
}
这是可靠的原则之一(依赖注入)


我反对这种做法。这是可能的,但会使
文档
对象难以使用,因为属性现在取决于它是如何实例化的。例如,您可以添加第二个属性
otherDetails
,该属性的类型为
readonly Record
,任何不属于
basicDetails
的内容都会出现在该属性中。这使得
文档
对象API更加稳定。@VLAZ实际上,文档的本质是动态的。将要发送给我们的数据看起来像:
{basicDetails:{},…插入任何东西..}
所以除了基本细节之外,我们不知道也不关心发送的是什么。这是固定的。其他一切。。我们只是将它存储在DB中,而不关心它的有效性。@VLAZ我知道您建议将任何变量都保存在fixed property
otherDetails
中,但我们无法控制它。“我们所知道的是,我们将在根部得到一个固定结构的基本细节。”弗拉兹在我考虑poss时说道
let obj = { basicDetails: { type: "draft" }, lineDetails:{ lined : 123, itemName : "itemName" } };

class BasicDetails {
    type /*: string */;
    createdDate /*: Date */;
    constructor(basicDetails /*:basicDetails */) {
        this.type = basicDetails.type;
        this.createdDate = new Date();
    }
}

const { basicDetails, ...rest } = obj

const doc = new Document( new BasicDetails(basicDetails), rest )