Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
331 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# Custom setters and getters | ||
|
||
Sometimes it may be necessary to have custom setters and/or getters for some attributes. Structure allows you to do that using native JavaScript setters and getters. It will even support coercion. | ||
|
||
It's important to notice that you **should not** try to access the attribute directly inside its getter or to set it directly inside its setter because it will cause infinite recursion, this is default JavaScript behavior. To access an attribute value inside its getter you should use `this.get(attributeName)`, and to set the value of an attribute a setter you should use `this.set(attributeName, attributeValue)`: | ||
|
||
```js | ||
const User = attributes({ | ||
firstName: String, | ||
lastName: String, | ||
age: Number, | ||
})( | ||
class User { | ||
get firstName() { | ||
return `-> ${this.get('firstName')}`; | ||
} | ||
|
||
set lastName(newLastname) { | ||
return this.set('lastName', `Mac${newLastName}`); | ||
} | ||
|
||
get age() { | ||
// do NOT do that. Instead, use this.get and this.set inside getters and setters | ||
return this.age * 1000; | ||
} | ||
|
||
// this is NOT an attribute, just a normal getter | ||
get fullName() { | ||
return `${this.firstName} ${this.lastName}`; | ||
} | ||
} | ||
); | ||
|
||
const user = new User({ firstName: 'Connor', lastName: 'Leod' }); | ||
|
||
user.firstName; // -> Connor | ||
user.lastName; // MacLeod | ||
user.fullName; // -> Connor MacLeod | ||
``` | ||
|
||
## Inheritance | ||
|
||
Custom setters and getters are also inherited, be your superclass a pure JavaScript class or another structure: | ||
|
||
```js | ||
class Person { | ||
// If Person was a structure instead of a pure class, that would work too | ||
get name() { | ||
return 'The person'; | ||
} | ||
} | ||
|
||
const User = attributes({ | ||
name: String, | ||
})(class User extends Person {}); | ||
|
||
const user = new User({ name: 'Will not be used' }); | ||
|
||
user.name; // -> The person | ||
``` | ||
|
||
**Important** | ||
|
||
JavaScript nativelly won't let you inherit only one of the accessors (the getter or the setter) if you define the other accessor in a subclass: | ||
|
||
```js | ||
class Person { | ||
get name() { | ||
return 'Person'; | ||
} | ||
} | ||
|
||
class User extends Person { | ||
set name(newName) { | ||
this._name = newName; | ||
} | ||
} | ||
|
||
const user = new Person(); | ||
user.name = 'The user'; | ||
user.name; // -> The user | ||
``` | ||
|
||
It happens because _once you define one of the accessors in a subclass_, all the accessors for the same attribute inherited from the superclass will be ignored. | ||
|
||
While it's a weird behavior, Structure will follow the same functionality so the Structure classes inheritance work the same way of pure JavaScript classes, avoiding inconsistencies. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
const { ATTRIBUTES } = require('../symbols'); | ||
|
||
exports.setInInstance = function setAttributesInInstance(instance, attributes) { | ||
Object.defineProperty(instance, ATTRIBUTES, { | ||
configurable: true, | ||
value: attributes, | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
module.exports = { | ||
SCHEMA: Symbol('schema'), | ||
ATTRIBUTES: Symbol('attributes'), | ||
DEFAULT_ACCESSOR: Symbol('defaultAccessor'), | ||
}; |
3 changes: 3 additions & 0 deletions
3
packages/structure/test/unit/__snapshots__/instanceAndUpdate.spec.js.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`instantiating a structure custom setters and getters when tries to set an attribute that does not exist fails and throws an error 1`] = `"NOPE is not an attribute of this structure"`; |
Oops, something went wrong.