jsdk-offical
Version:
JSDK is the most comprehensive TypeScript framework, like JDK.
184 lines (156 loc) • 5.59 kB
Markdown
Since version 2.5, JSDK abstracts many of advanced syntax features from jscore module to new <b>jsugar</b> module. For some modules such as <b>jsmvc/jsvp/jsunit</b>, these syntax sugars such as <b>reflec/annotation/aop</b> is basic and indispensable; However, for other modules, it is not required at all. Therefore, it is a better way to use these features as a separate library for choosing by other libraries.
* jsunit/jsmvc/jsvp has been configured to import jsugar automatically.
## Annotation
Annotation provides more additional information for class, is also foundation feature of AOP and DI.
### Usage of Annotation
Let's take a look at example code:
```javascript
@deprecated()
export class MyClass {
@deprecated()
public name;
@deprecated()
public clone() {
}
}
```
- *@deprecated is an annotation function provided by JSDK, prints warning message on console to indicate that a class or property or method has been discarded.*
### Predefined Annotations
JSDK has defined the following annotation functions, which can be used directly:
Annotation|In Module|Scope
---|---|---
@klass|jsugar|class
@deprecated|jsugar|class/method/field
@before|jsugar|method
@after|jsugar|method
@around|jsugar|method
@throws|jsugar|method
@compo|jsmvc|class
@inject|jsmvc|field
@widget|jsfx|class
- *See api doc for parameters of annotation function*
### Custom Annotation
Suppose you want to define a new annotation: <code>@version</code>, it is used to record the version of class.
1. Define new annotation
```javascript
export function version(ver: string): any {
return Annotations.define({
name: 'version',
handler: (anno: string, values: Array<string>, klass: Function) => {
//do you want
},
target: AnnotationTarget.CLASS
}, [ver]);
}
```
2. Read annotation value
```javascript
@version('1.2.3')
export class MyClass {
}
Konsole.print(Annotations.getValue(version, MyClass)); //print: 1.2.3
```
## Reflection
Reflection is a mechanism for dynamically obtaining the information of class properties and methods at runtime.
It allows us to dynamically instantiate a class, dynamically call its methods and dynamically read or write its properties.
- *The reflection functions of JSDK is provided by <b> JS.reflect.Class</b>. If you have know Java, it will be easier to understand.*
### Make Reflectable Class
Unlike Java, not every JS class supports reflection. JSDK has two ways to make a class supports reflection.
<b>[Way 1]</b><br>
When define a class, use annotation <code>@klass</code> to mark it as reflectable class.
```javascript
module WHO {
export namespace virus {
@klass('WHO.virus.Convid19') //Argument must be full name of the class
export class Convid19 {
}
}
}
```
<b>[Way 2]</b><br>
You can also use tool method. (This way is more suitable for classes that cannot be annotated)
```javascript
Class.reflect(Convid19, 'WHO.virus.Convid19');
```
* Native <b>Object</b> class already supports reflection in jsugar.
<br>
<b>Tip:</b> The following annotations can mark a class to support reflection:
- @klass
- @compo
- @widget
### Use of Reflections
When a class supports reflection, you can access more inner informations using its reflection class.
1. Get reflect Class
```javascript
let cls1 = Convid19.class;
Konsole.print(cls1) //print the reflect Class of Convid19
let cls2 = new Convid19().getClass();
Konsole.print(cls2) //print the reflect Class of Convid19
let cls3 = Class.forName('WHO.virus.Convid19');
Konsole.print(cls3) //print the reflect Class of Convid19
Konsole.print(cls1===cls2 && cls2===cls3) //print true
```
2. Get methods and fields
```javascript
let c = new Convid19(),
cls = c.getClass();
Konsole.print(cls.getKlass()); //print Convid19
Konsole.print(cls.methods()); //print all static methods and instance methods
Konsole.print(cls.fields(c)); //print all static fields and instance fields
```
3. Reflective instantiation
```javascript
let c = Class.newInstance('WHO.virus.Convid19'); //equals: new Convid19();
```
## AOP
AOP is mechanism of replacing for the original function or method. New function can be implanted at a cut point to modify its original behavior.
<b>jsugar</b> supports the following cut points of AOP:
- before
- around
- after
- throws
You can AOP a function in <b>jsugar</b>:
```javascript
let format = function(s: string){
return ' ' + s + ' '
}
let trim = format.aop({ //Returns a new modified function
before: (s: string) => {
...
},
around: function (fn: Function, s: string) {
return fn.apply(this, [s&&s.trim()])
},
after: (returns: string) => {
...
}
})
```
*Note: the original function has not been changed*
You also can AOP a method of class using its reflectable class in <b>jsugar</b> :
```javascript
Date.class.aop('format', {//The 'format' method of Date class be changed.
before: (format: string) => {
Assert.equal(s, format);
},
around: function (fn: Function, format: string) {
return (<string>fn.apply(this, [format])).replace('1900-', '2019-')
},
after: (returns: string) => {
Assert.true(returns.startsWith('2019-'));
}
})
```
*Note: The class method has been changed. If you need to restore the original method, execute cancelAop:*
```javascript
Date.class.cancelAop('format');
```
You also can AOP a method of class by AOP annotations in <b>jsugar</b>:
```javascript
class Me {
@before((s)=>{return s+'\n'})
format(s:string){
return s
}
}
```