【问题标题】:TypeError: Cannot add property 1, object is not extensible↵ at Array.push (<anonymous>)类型错误:无法添加属性 1,对象不可扩展↵ 在 Array.push (<anonymous>)
【发布时间】:2019-02-28 17:14:42
【问题描述】:

我正在尝试向数组添加一些数据,但出现不可扩展错误。

组件代码:

this._store.select(p => p.collection.workspaceCollectionPages).subscribe((data: CollectionPageDbModel[]) =>{
      if(data){
      return data.map((collectionPageDbModel)=> {

      this.collectionPages.push(collectionPageDbModel) //Getting error on this line while pushing

    });}

我的数据变量中有四个对象,我试图将它们推送到 collectionPages 中,但推送时出现可扩展错误。

我需要添加更多数据的 collectionPage 数组

这个数据我需要推送

CollectionPageDbModel:

export class CollectionPageDbModel implements IDbModel {
  public id?: number;
  public collection_version_id: number;
  public user_id?: string;
  public name: string;
  public position?: number = 0;
  public contents: string;
  public created_at?: string;
  public updated_at?: string;
  public server_id?: any;

}

谁能帮我解决这个问题

【问题讨论】:

  • 请将collectionPageDbModel 类添加到您的问题中
  • collectionPages 之后会发生什么?在this._store.select( 之后
  • 在将新对象推送到 collectionPages 时会抛出对象不可扩展错误
  • 您是否在任何地方使用preventExtensions 或将this.collectionPages 对象传递给可能执行此操作的函数?即使在store.select 之后,由于 javascript 事件队列,这也会导致问题
  • 为什么会有return 声明?我认为那里不需要这样做,因为您只是将对象推入内部。尝试删除return ,您可以将其用作其他选项,例如this.collectionPages = [...this.collectionPages, collectionPageDbModel]

标签: angular typescript rxjs


【解决方案1】:

使用 Object.assign 方法复制对象并重试,

this.collectionPages = Object.assign([], this.collectionPages);
this.collectionPages.push(collectionPageDbModel);

【讨论】:

  • 为什么复制对象可以解决问题?有没有 js6 解决方案?
  • @AliSaberi 晚了,但我认为状态元素/属性应该是不可变的。您是否尝试过从那里改变数组的操作?
  • @AliSaberi 我认为更多的 JS6 解决方案是:this.collectionPages = [...this.collectionPages, collectionPageDbModel]
【解决方案2】:

Daniel 提出的解决方案当然适用于这种情况。原因是每个 JS 对象都有的对象描述符。你可以通过调用Object.getOwnPropertyDescriptors(obj) 来检查它们,它也适用于数组,因为(几乎)所有东西都是一个对象。

问题中最可能使用的 NGRX 存储选择器使用 Object.defineProperties(obj) 修改对象描述符。这样做是为了防止在 Reducer 之外的 Store 中的数据发生任何突变(它也不会改变状态,只是创建一个新状态)。

一般情况下,您必须克隆要变异的对象:


import { cloneDeep } from 'lodash'

// ...

constructor(private store: Store<any>) {}

someMethod() {
  let someDataFromTheStore = cloneDeep(this.store.select(selectSomeData))
  someDataFromTheStore.myArray.push('...')
}


Object.assigncloneDeep 都不会将描述符传输到新副本。

Object.getOwnPropertyDescriptors

Object.defineProperties

【讨论】:

    【解决方案3】:

    这个工作,

    if(data){
       const result = data.map((collectionPageDbModel)=> {
          this.collectionPages.push(collectionPageDbModel) //Getting error on this line while pushing
       });
       
       return result
       // incase of async call this one will work fine
       // return Promise.all(result)
    }
    

    【讨论】:

      【解决方案4】:

      尝试将数据推送到数组时,我遇到了类似的错误警告。 我的解决方案是使用扩展运算符而不是 push:

      let myarray: any = [];
      const data = {
                  answers: [],
                  score: 24,
                  ctime: '',
      };
      myarray = [...myarray, data]; // used this instead of push
      

      【讨论】:

        猜你喜欢
        • 2021-12-09
        • 2017-09-19
        • 2020-04-26
        • 2021-02-02
        • 1970-01-01
        • 2020-11-15
        • 1970-01-01
        • 2019-08-29
        • 2021-10-13
        相关资源
        最近更新 更多