【问题标题】:TypeError: "name" is read-only类型错误:“名称”是只读的
【发布时间】:2019-01-13 01:16:00
【问题描述】:

我正在尝试在 Sharepoint Framework 小示例中实现原型模式,我从这里获取示例:

https://mertarauh.com/tutorials/typescript-design-patterns/prototype-pattern/

并改编如下:

 class Employee  {

    private totalperMonth: number;


    constructor(public name: string, public hiredDate: Date, public dailyRate: number){
        this.totalperMonth = dailyRate * 20 ;
    }

    public display(): string{
        return "Employee " + this.name + " earns per month: " + this.totalperMonth;
    }

    public clone():Employee{
        var cloned = Object.create(Employee || null);
        Object.keys(this).map((key: string) => {
            cloned[key]= this[key];
        });
        return <Employee>cloned;
    }
}

export default Employee;

和组件

import * as React from 'react';
import styles from './Prototype.module.scss';
import { IPrototypeProps } from './IPrototypeProps';
import { escape } from '@microsoft/sp-lodash-subset';
import  Employee from './Employee';


export default class Prototype extends React.Component<IPrototypeProps, {}> {


  public render(): React.ReactElement<IPrototypeProps> {
    const today = new Date();
    let employee1: Employee = new Employee('Luis', today, 500);
    let employee2 = employee1.clone();
    employee2.dailyRate = 550;

    return (
      <div className={ styles.prototype }>
        <div className={ styles.container }>
          <div className={ styles.row }>
            <div className={ styles.column }>
              <span className={ styles.title }>Welcome to SharePoint!</span>
              <p className={ styles.subTitle }>Customize SharePoint experiences using Web Parts.</p>
              <p className={ styles.description }>{escape(this.props.description)}</p>
                <span className={ styles.label }>{employee1.display()}</span>
                <span className={ styles.label }>{employee2.display()}</span>
            </div>
          </div>
        </div>
      </div>
    );
  }
}

但是我在控制台中遇到了这个错误:

我错过了什么?

【问题讨论】:

  • 我不习惯 sharepoint 框架,但是在使用 Jest 进行测试时,我在处理不变性方面遇到了一些麻烦。就我而言,使用 Object.defineProperty 可以解决这个问题:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
  • 你是否在任何地方定义了 name 变量?

标签: reactjs typescript


【解决方案1】:

这种方法存在几个问题。

类是 TypeScript 中的一等公民,替代的继承方法会使类型安全变得不那么简单。

Object.create 是低级工具,除非您知道自己在做什么以及为什么,否则使用它不是一个好主意。这里的实际错误是选择了错误的原型(Employee 而不是Employee.prototype),所以name 属性指的是function name property,它是只读的,不应重新分配。实现clone 的正确方法是:

public clone():Employee{
    return Object.assign(Object.create(Employee.prototype), this);
}

它忽略类构造函数的事实是一个值得怀疑的决定,因为构造函数可能包含与clone 中应用的逻辑不同的逻辑。

React 提倡函数式编程作为 OOP 的替代品,将应用程序状态维护为普通对象而不是类实例是有益的,这可能有助于避免将来修复成本高昂的设计缺陷。在这种情况下,没有什么真正需要课程。同样的事情可以表示为:

const createEmployee = (name, hiredDate, dailyRate) => ({
 name,
 hiredDate,
 dailyRate,
 totalperMonth: dailyRate * 20
});

...

let employee1 = createEmployee('Luis', today, 500);
let employee2 = {...employee1, dailyRate: 550};

请注意,totalperMonth 不会在 Employee 类和 createEmployee 工厂函数中重新计算。这可能是不可取的(参见上面关于构造函数的注释)。

【讨论】:

  • 我只是想在一个简单的反应组件中实现原型模式,我已经解决了 name readonly 错误,通过显式声明属性而不是在构造函数中,但仍然出现此错误:@987654322 @
  • 我不会说这种模式在 React 中是有益的,所以它可能是反模式。无论如何,答案已经解释了问题所在。你使用了错误的原型。您链接的问题中的答案也不正确。 Object.getPrototypeOf(Employee) === Function.prototype。那也是错误的原型。正确的原型是Employee.prototype。请注意,totalperMonth 不会被重新计算。这是预期的行为吗?
猜你喜欢
  • 2016-08-27
  • 1970-01-01
  • 2015-11-22
  • 2018-03-31
  • 1970-01-01
  • 1970-01-01
  • 2017-08-27
  • 1970-01-01
  • 2020-05-25
相关资源
最近更新 更多