# 脚本语法详解

## for循环

### 循环集合
```javascript
var list = [1,2,3];
for(index,item in list){    //如果不需要index，也可以写成for(item in list)
    println(index + ":" + item);
}
// 结果：0:1, 1:2, 2:3
```

### 循环指定次数
```javascript
var sum = 0;
for(value in range(0,100)){    //包括0包括100
    sum = sum + value; //不支持+= -= *= /= ++ -- 这种运算
}
return sum; // 5050
```

## while循环
```javascript
var count = 100;
var sum = 0;
while(count){
    sum = sum + count;
    count = count - 1;
}
return sum; // 5050
```

## 循环map
```javascript
var map = {
    key1 : 123,
    key2 : 456
};
for(key,value in map){    //如果不需要key，也可以写成for(value in map)
    println(key + ":" + value);
}
// 结果：key1:123, key2:456
```

## Import导入

### 导入Java类
```javascript
import 'java.lang.System' as System;
import 'javax.sql.DataSource' as ds;
import 'org.apache.commons.lang3.StringUtils' as string;
import 'java.text.*'    // 此写法跟Java一致

System.out.println('调用System打印');
System.out.println(ds);
System.out.println(string.isBlank(''));
System.out.println(new SimpleDateFormat('yyyy-MM-dd').format(new Date()));
```

### 导入已定义的模块
```javascript
import log; //导入log模块，并定义一个与模块名相同的变量名
//import log as logger; //导入log模块，并赋值给变量 logger
log.info('Hello {}','Magic API!')
```

## new创建对象
```javascript
import 'java.util.Date' as Date;//创建之前先导包，不支持.*的操作
return new Date();
```

## 异步调用

### 异步调用方法
```javascript
var val = async db.select('.....'); // 异步调用，返回Future类型
return val.get();   //调用Future的get方法
```

### 异步调用lambda
```javascript
var list = [];
for(index in range(1,10)){
    list.add(async (index)=>db.selectInt('select #{index}'));
}
return list.map(item=>item.get());  // 循环获取结果
```

## exit
语法格式为 `exit expr[,expr][,expr]....`

在`magic-api`中只取前三个值，分别对应`code`、`message`、`data`

如：`exit 400,'参数填写有误'`

## assert
语法格式为 `assert expr : expr[,expr][,expr]....`

如：`assert a == 1 : 400, 'a的值应为1'` 相当于
```javascript
if(a != 1){
    exit 400, 'a的值应为1'
}
```

## 类型转换
通过`::`进行类型转换，如`xxx::int`、`xxx::double`等，当前支持转换类型有`int`、`double`、`long`、`byte`、`short`、`float`、`date`

```javascript
var a = "1";
return {
    v1: a::int,
    v2: a::int(0),  //转换失败时，值为0
    v3: "2020-01-01"::date('yyyy-MM-dd') //转为Date
}
```

`::sql`支持将数据转换为对应的sql类型，比如：
```javascript
img::sql('blob')
```
可传入的参数请参考`java.sql.Types`中定义的常量，不区分大小写。

## 嵌入其它脚本语言
```javascript
var name = "hello";
var test = ```javascript
    name + ' ~ world'
```;
return test();
```

## 可选链操作符
可选链操作符(`?.`)允许读取位于连接对象链深处的属性的值，而不必明确验证链中的每个引用是否有效。

```javascript
var a = null;
var b = a?.name;    // b = null;
var c = a?.getName();   // c = null;
```

## 扩展运算符
扩展运算符，又叫展开语法(Spread syntax)，是用于将list或map在语法层面展开

### lambda 调用
```javascript
var sum = (a,b,c) => a + b + c;
System.out.println(sum(...[1,2,3])) // 结果：6
```

### list 展开
```javascript
var arr = [3,4,5];
System.out.println([1,2,...arr,6,7]) // 结果：[1, 2, 3, 4, 5, 6, 7]
```

### map 展开
```javascript
var map = {key2:2}
System.out.println({key1:1,...map,key3:3}) // 结果：{key1=1, key2=2, key3=3}
```
