«Вычисляемое свойство» в классе Vanilla Javascript

Функция вычисляемые свойства распространена в популярных JS-фреймворках (React, VueJS), но как мы реализуем ее в vanilla JS?

Предположим, что для данного класса User со свойством dateOfBirth мы хотели бы вычислить его age, есть ли лучший способ выполнить эту задачу, чем приведенный ниже код?

function User(name, dateOfBirth) {
    this.name = name;
    this.dateOfBirth = dateOfBirth;

    this.age = function() {
        return now() - this.dateOfBirth;
    }
}

var driver = new User('Steve', new Date('12 December, 1990'))
driver.age()

В приведенном выше коде мы получаем значение age, вызывая метод. Однако возможно ли получить значение только с помощью driver.age?

Здесь нет вычисляемых имен свойств. Лучше поставить age на прототипе

Snow 15.05.2019 10:26

да, вы можете использовать getter

Jaromanda X 15.05.2019 10:27

Хотя код, который вы представили, очень неполный

Jaromanda X 15.05.2019 10:30

связанные: stackoverflow.com/questions/4822953/…

Matt Ellen 15.05.2019 10:36
Поведение ключевого слова "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) для оценки ваших знаний,...
3
4
1 895
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Является ли это «лучше» или нет, это вопрос стиля/мнения, но если вам нужно свойство, а не метод, вы можете создать свойство доступа, в вашем случае аксессор с добытчик, но без сеттер.

Внося минимальные изменения в свой код, вы бы сделали это так:

function User(name, dateOfBirth) {
    this.name = name;
    this.dateOfBirth = dateOfBirth;

    Object.defineProperty(this, "age", {
        get() {
            return now() - this.dateOfBirth;
        }
    });
}

Живой пример:

function now() { return Date.now(); }
function User(name, dateOfBirth) {
    this.name = name;
    this.dateOfBirth = dateOfBirth;

    Object.defineProperty(this, "age", {
        get() {
            return now() - this.dateOfBirth;
        }
    });
}

var steve = new User("Steve", new Date(1990, 11, 12));
console.info(steve.age);

Вы можете определить их более кратко, используя инициализатор объекта (обратите внимание, что в этом примере отбрасывается объект, созданный с помощью new User, и вместо этого возвращается другой, у которого нет User.prototype в качестве прототипа):

function User(name, dateOfBirth) {
    return {
        name,
        dateOfBirth,
        get age() {
            return now() - this.dateOfBirth;
        }
    };
}

Живой пример:

function now() { return Date.now(); }
function User(name, dateOfBirth) {
    return {
        name,
        dateOfBirth,
        get age() {
            return now() - this.dateOfBirth;
        }
    };
}

var steve = new User("Steve", new Date(1990, 11, 12));
console.info(steve.age);

Я также использовал новый (ES2015+) сокращенный синтаксис свойства для name и dateOfBirth.

Это также совместимо с синтаксисом class ES2015:

class User {
    constructor(name, dateOfBirth) {
        this.name = name;
        this.dateOfBirth = dateOfBirth;
    }
    get age() {
        return now() - this.dateOfBirth;
    }
}

Живой пример:

function now() { return Date.now(); }
class User {
    constructor(name, dateOfBirth) {
        this.name = name;
        this.dateOfBirth = dateOfBirth;
    }
    get age() {
        return now() - this.dateOfBirth;
    }
}

var steve = new User("Steve", new Date(1990, 11, 12));
console.info(steve.age);

Есть ли очевидное преимущество во втором примере кода, где user.prototype не создается?

puoygae 15.05.2019 10:38

@puoygae - это созданный, просто он не используется. Это также вопрос стиля. Лично мне не нравится использовать new X, если только я не использую X.prototype (напрямую или через синтаксис class). Так что, если бы я выбрал второй вариант, я бы, вероятно, назвал его createUser и назвал бы его без new. Но мне нравятся прототипы и мне нравится new, поэтому сейчас я склоняюсь к синтаксису class.

T.J. Crowder 15.05.2019 10:39

да. Вы можете использовать getter для возврата вычисленного значения, например:

class User {
  constructor(name, dateOfBirth) {
    this.name = name;
    this.dateOfBirth = dateOfBirth;
  }

  get age() {
    return new Date() - this.dateOfBirth;
  }
}

var driver = new User('Steve', new Date('12 December, 1990'));
console.info(driver.age);

Дополнительная информация здесь.

Спасибо за этот ответ. Хотя этот ответ правильный и даже использует последний класс ES6, я решил выбрать T.J. Ответ Краудера, потому что он соответствует версии JS, которую я использовал в своем вопросе.

puoygae 15.05.2019 10:39

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

Поиск значений заполнителей в 2 строках
Как получить конкретные данные из базы данных postgresql, когда пользователь входит в систему после того, как администратор назначает данные с помощью codeigniter?
Почему нельзя использовать let для объявления переменной с тем же именем, что и у одного параметра функции, даже если для параметра установлено значение по умолчанию?
Сопоставление массивов и фильтрация ReactJ
Я получаю синтаксическую ошибку, когда пытаюсь использовать функцию карты массива в скриптах Google. Почему?
Как динамически добавлять идентификаторы в строки таблицы, чтобы их можно было идентифицировать однозначно
Мне нужно обновить API внутри componentDidMount после того, как я setState в рендере
Есть ли способ передать свойство объекта в v-for для данных Vue?
Javascript: дождитесь завершения вызова AJAX, прежде чем инициировать действие, инициированное пользователем
Как отфильтровать внешний массив на основе внутреннего массива?