can-define
Version:
Create observable objects with JS dot operator compatibility
127 lines (96 loc) • 4.18 kB
Markdown
{function} can-define
can-observables
can-legacy
Defines observable properties and their behavior on a prototype object. This
function is not commonly used directly. [can-define/map/map]
and [can-define/list/list] are more commonly used. Types and
behaviors shared by both [can-define/map/map]
and [can-define/list/list] are documented here.
can-define.static 0 static
can-define.typedefs 1 types
can-define.behaviors 2 behaviors
../package.json
true
`define(prototype, propDefinitions)`
The `define` function can be used to define observable properties, type conversion, and getter/setter logic on [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain prototype objects]. The `define` function is used by [can-define/map/map] and [can-define/list/list] to
create observables. However, `define` can be used to create observables from types that
do not inherit from [can-define/map/map] and [can-define/list/list].
For more information on observables and how they are used in CanJS, please read
the [guides/technology-overview].
The following creates a `Greeting` type which will have observable `message`
properties:
```js
import {define, Reflect as canReflect} from "can";
const Greeting = function( message ) {
this.message = message;
};
define( Greeting.prototype, {
message: { type: "string" }
} );
const greeting = new Greeting("Hello");
canReflect.onKeyValue(greeting, "message", (newValue) => {
console.log( newValue ); //-> logs "goodbye"
});
greeting.message = "goodbye";
```
{Object} prototype The prototype object of a constructor function or [class](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/class). The prototype object will have getter/setters defined on it that carry out the defined behavior. The prototype will also contain all of [can-event-queue/map/map]'s methods.
{Object<String,can-define.types.propDefinition>} propDefinitions An object of properties and their definitions. For example, a property (`propertyName`) has a [can-define.types.propDefinition] object with zero or more of the following behaviors:
```js
define(Type.prototype, {
propertyName: {
default: function() { /* ... */ },
Default: Constructor,
type: function() { /* ... */ },
Type: Constructor,
get: function() { /* ... */ },
value: function() { /* ... */ },
set: function() { /* ... */ },
serialize: function() { /* ... */ },
identity: Boolean
}
})
```
## Use
`can-define` provides a way to create custom types with observable properties.
Where [can-define/map/map] and [can-define/list/list] provide more functionality, they also make
more assumptions on the type constructor. `can-define` can be used
to create completely customized types.
The following creates a `Person` constructor function that
will be used to create `Person` instances with observable properties:
```js
import {define} from "can";
// Define the type
const Person = function( first, last ) {
this.first = first;
this.last = last;
};
define( Person.prototype, {
first: { type: "string" },
last: { type: "string" },
fullName: {
get: function() {
return this.first + " " + this.last;
}
}
} );
// Create an instance
const person = new Person( "Justin", "Meyer" );
console.log( person.first ); //-> "Justin"
console.log( person.last ); //-> "Meyer"
console.log( person.fullName ); //-> "Justin Meyer"
person.on( "fullName", function( ev, newVal, oldVal ) {
console.log( newVal ); //-> "Ramiya Meyer"
console.log( oldVal ); //-> "Justin Meyer"
} );
person.first = "Ramiya";
```
The observable properties call [can-observation-recorder.add ObservationRecorder.add] so they can be automatically by
[can-observation] (and therefore [can-stache]).
## Mixed-in instance methods and properties
`define` adds the following methods from
[can-event-queue/map/map]:
{{#each (getChildren [can-event-queue/map/map])}}
- [{{name}}] - {{description}}{{/each}}