Какова цель Object.assign() в конструкторе объекта Typescript?

Где-то по пути я добавил конструктор в свой класс Todo:

export class Todo {
  id: number;
  title: string;
  complete: boolean = false;
  editMode: boolean = false;

  constructor(values: Object = {}) {
    Object.assign(this, values);
  }
}

Я не понимаю назначение кода в конструкторе.

Мое приложение работает как с ним, так и без него, но я не решаюсь удалить код

Какова цель Object.assign(...) в этом конструкторе?

Не уверен, почему ответ был удален, единственная неверная часть ответа была очевидным «эквивалентным» кодом.

Jaromanda X 09.04.2019 03:16
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
7
1
11 594
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Это просто объединение двух объектов this и values. Согласно МДН

The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object. It will return the target object.

Он используется для создания мелкой копии объекта и объединения его свойств с this, который является экземпляром Todo. В заданном вами коде this целевой объект. Рассмотрим приведенный ниже пример

let target = {a:1,b:2};
Object.assign(target,{x:"new prop 1",y:"new prop 2"});
console.info(target) 
is equivalent to это может быть эквивалент, но вы не можете сделать это с this, и это не совсем эквивалент для других объектов
Jaromanda X 09.04.2019 03:12

как я уже сказал, вы не можете так присваивать this, так что это вообще не сработает - но даже при работе с другими объектами это совсем не результат такой же...

Jaromanda X 09.04.2019 03:14

@JaromandaX Я получил часть this. Но все еще не могу понять, почему оба не работают одинаково для другого объекта. Не могли бы вы привести пример?

Maheer Ali 09.04.2019 03:24

@MaheerAli вы потеряете неисчислимые свойства

zerkms 09.04.2019 03:31

есть еще разница это... (смотрите в консоли)

Jaromanda X 09.04.2019 03:32

Я думаю, что точка zerkms, вероятно, более важна @MaheerAli, но вы можете видеть, что есть разница (изначально вы сказали эквивалентно, и это нормально, но если кто-то не знает, что делает Object.assign, то нотация {...x}, вероятно, запутает их еще больше :р

Jaromanda X 09.04.2019 03:36
Ответ принят как подходящий

Это метод простого добавления значений параметров класса в соответствующие поля класса, где класс реализует этот интерфейс или, по крайней мере, имеет частичную имплантацию этого интерфейса.

interface IPerson {
  firtName: string;
  lastName: string;
}

class Person implements IPerson {
  public firtName!: string;
  public lastName!: string;

  constructor(params: IPerson) {
    Object.assign(this, params);
  }
}

Ваше приложение работает, потому что вы, кажется, реализовали это таким образом, что значения обратного вызова values также достаточно.

Основная проблема с этим взломом заключается в том, что Object.assign не является типобезопасным. Таким образом, использование его таким образом противоречит сути TypeScript.

Если вы хотите сделать это безопасным способом, вам лучше использовать пользовательскую реализацию, в которой тип правильно проверяется. Что-то вроде этого:

type PDM = PropertyDescriptorMap;

export class ClassSAssign<T> {
  constructor(private objectToSpread: T, private klass: T) {}

  private propertyDescriptorOptions = {
    enumerable: true,
    writable: true
  };

  public apply(): void {
    const map = this.getPropertiesDescriptorMap();
    Object.defineProperties(this.klass, map);
  }

  private getPropertiesDescriptorMap(): PDM {
    return Object.entries(this.objectToSpread).reduce(
      (obj: PDM, entry) => this.getPropertyDescriptorMap(obj, entry),
      {}
    );
  }

  private getPropertyDescriptorMap(obj: PDM, [key, value]: [string, any]): PDM {
    return {
      ...obj,
      [key]: {
        value,
        ...this.propertyDescriptorOptions
      }
    };
  }
}

и вы можете использовать эту утилиту следующим образом:

class Person implements IPerson {
  public firtName!: string;
  public lastName!: string;

  constructor(params: IPerson) {
    new ClassSAssign(params, this).apply();
  }
}

Если вы не хотите/не хотите использовать вышеизложенное, я предлагаю вам, по крайней мере, добавить некоторую строгость типов, чтобы защитить ваш класс от того, какие значения могут быть переданы в него.

interface IToDo {
  id?: number;
  title?: string;
}

export class Todo implements IToDo {
  public id?: number;
  public title?: string;
  public complete: boolean = false;
  public editMode: boolean = false;

  constructor(values?: IToDo) {
    Object.assign(this, values);
  }
}

Object.assign присваивает все свойства второго аргумента первому аргументу.

Что делает код, так это то, что если вы передаете объект в конструктор, он присваивает эти свойства создаваемому объекту. Так, например:

const todo = new Todo({ id: 1, title: 'hello' });
console.info(todo.title); // 'hello'

Редактировать: Поскольку Object.assign не является типобезопасным, вам, вероятно, следует заставить конструктор принимать что-то более конкретное, чем просто Object. Я бы предложил создать для него интерфейс.

Object.assign не имеет проверки типов. Альтернативой может быть:

const assign = <T, K extends keyof T>(...args: T[]): T =>
    args.reduce( (result, current) =>
        (Object.keys(current) as K[]).reduce((target, key) => {
            target[key] = current[key];
            return target;
        }, result)
    , args[0])
;

Обратите внимание, что если свойства T не являются необязательными, каждый переданный объект должен включать каждое свойство. Если вы можете гарантировать наличие каждого свойства после возврата функции, вы можете передать аргументы как Partial<T>, а затем принудить результат, когда закончите.

Можно утверждать, что, поскольку Object.keys также не имеет проверки типов, вы действительно не приблизились к нирване типов. Вы только что добавили некоторый код, чтобы лучше скрыть приведение, и добавили ограничения, которые могут не соответствовать проблемам, для решения которых часто используется Object.assign.

Superole 07.12.2021 13:20

Другие вопросы по теме