# Computed Properties

## Overview

Computed properties are properties derived from the value of one or more properties on the current instance. For example, the `fullName` property on the `Person` class is defined as a method. But, we could define it as a property based on the `firstName` and `lastName` property.&#x20;

Unlike methods, computed properties are accessed like any other data property defined on the class itself. Likewise, computed properties can optionally be iterated over.

## Types of Computed Properties

We support the following types of computed properties:

* [Read-Write Properties](/developer-guide/the-object-model/computed-properties.md#read-write-properties)
* [Read-only Properties](/developer-guide/the-object-model/computed-properties.md#read-only-properties)
* [Constant Properties](/developer-guide/the-object-model/computed-properties.md#constant-properties)

### Read-Write Properties

*Read-write properties* are defined using the `computed()` method, and passing it an initialization hash. The should have a getter method, and an optional setter method. Let's see how we can redefine our `Person` class using computed properties.

{% code title="person.js" %}

```javascript
const { BO, computed } = require ('@onehilltech/blueprint');

const Person = BO.extend ({
  fullName: computed ({
    set (value) {
      [this.firstName, this.lastName] = value.split (' ');    
    }
    
    get () {
      return `${this.firstName} ${this.lastName}`;
    }
});
```

{% endcode %}

{% hint style="info" %}
Use the `computed()` method to define computed property on the class definition.
{% endhint %}

&#x20;We can then just use the computed property like any other data property.

```javascript
let person = new Person ({firstName: 'Bill', lastName: 'Clinton'});
console.log (person.fullName);            // "Bill Clinton"

person.fullName = 'Ronald Reagan';
console.log (person.fullName);            // "Ronald Reagan"
```

### Read-Only Properties

*Read-only properties* are defined in a similar manner as read-write properties. The main difference read-only properties do not have a `set` method on its computed property definition.

```javascript
const { BO, computed } = require ('@onehilltech/blueprint');

const Person = BO.extend ({
  fullName: computed ({
    set (value) {
      [this.firstName, this.lastName] = value.split (' ');    
    }
});
```

Now, anytime we set the `fullName` property, it will not change.

```javascript
let person = new Person ({firstName: 'Bill', lastName: 'Clinton'});
console.log (person.fullName);            // "Bill Clinton"

person.fullName = 'Ronald Reagan';
console.log (person.fullName);            // "Bill Clinton"
```

### Constant Properties

*Constant properties* are computed properties that do not change. The behavior of a constant property is therefore similar to that of [read-only properties](/developer-guide/the-object-model/computed-properties.md#read-only-properties). The main difference is the constant properties are not computed at run-time. Instead, you must provide its value when you are defining the property.

Here is an example of defining a constant property named `MINIMUM_AGE` on the `Person` class.

{% code title="person.js" %}

```javascript
const { BO, computed } = require ('@onehilltech/blueprint');

const Person = BO.extend ({
  /// ...
  MINIMUM_AGE: computed.constant (21)
});
```

{% endcode %}

## Enumerable Computed Properties

When you enumerate the properties of an object, computed properties are not included in the enumeration. To enable enumeration of computed properties, add the `enumerable` property to the computed property descriptor.

```javascript
const { BO, computed } = require ('@onehilltech/blueprint');

const Person = BO.extend ({
  fullName: computed ({
    enumerable: true,      // the property can be enumerated
    get () { return `${this.firstName} ${this.lastName}`; }
    set (value) { [this.firstName, this.lastName] = value.split (' '); }
});
```

For [constant properties](/developer-guide/the-object-model/computed-properties.md#constant-properties), add the property descriptor after the constant value.

```javascript
const { BO, computed } = require ('@onehilltech/blueprint');

const Person = BO.extend ({
  /// ...
  MINIMUM_AGE: computed.constant (21, {enumerable: true})
});
```

Now, the computed properties will appear when the properties of the parent object are enumerated.

## Configurable Computed Properties

By default, computed properties are not configurable. This means that once a property is defined on a object, it cannot be redefined. For example, neither an extended class cannot change the property definition, nor an object instance during initialization time.&#x20;

To change this behavior, use the `configurable` property on the property descriptor.

```javascript
const { BO, computed } = require ('@onehilltech/blueprint');

const Person = BO.extend ({
  fullName: computed ({
    configurable: true,      // the property is configurable
    get () { return `${this.firstName} ${this.lastName}`; }
    set (value) { [this.firstName, this.lastName] = value.split (' '); }
});
```

For [constant properties](/developer-guide/the-object-model/computed-properties.md#constant-properties), add the `configurable` property to the property descriptor after the value.

```javascript
const { BO, computed } = require ('@onehilltech/blueprint');

const Person = BO.extend ({
  /// ...
  MINIMUM_AGE: computed.constant (21, {configurable: true})
});
```

Now, you can redefine the property in extended classes and during object initialization.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://blueprint.onehilltech.com/developer-guide/the-object-model/computed-properties.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
