data-type.md 11.5 KB
Newer Older
D
DCloud_LXH 已提交
1 2 3 4
## 数据类型@data-type

### 布尔值(Boolean)

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
5 6 7 8 9 10
布尔是简单的基础类型,只有2个值分别是:`true``false`

```ts
let a:boolean = true
let b = false
```
D
DCloud_LXH 已提交
11 12 13

### 数字(Number)

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
14 15 16 17 18
在web中,数字不区分整型和浮点。但在kotlin和swift中,数字需要是一个确定类型,比如Int、Float,没有泛数字。

UTS 在iOS和Android平台上新增了 number,拉齐了web端的实现,方便开发者写全端兼容代码。

Number是一个泛数字类型,包括整数或浮点数,包括正数负数。例如: 正整数 `42` 或者 浮点数 `3.14159` 或者 负数 `-1`
D
DCloud_LXH 已提交
19 20

```ts
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
21
// 以下都是number类型
D
DCloud_LXH 已提交
22
let a:number = 42
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
23 24 25
let b:number = 3.14159
let c = 42
let d = 3.14159
D
DCloud_LXH 已提交
26 27
```

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
28
注意:在UTS中,Number 是基本数据类型,是默认数字类型,开发者书写的字面量如果没有特别指定类型也自动识别为Number。
杜庆泉's avatar
杜庆泉 已提交
29

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
30
除了 number,UTS 在Android和iOS设备上,也可以使用kotlin和swift的专用数字类型:
杜庆泉's avatar
杜庆泉 已提交
31

D
DCloud_LXH 已提交
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
#### Kotlin 特有的数字类型 @Kotlin

- Byte, UByte
- Short, UShort
- Int, UInt
- Long, ULong
- Float
- Double

#### Swift 特有的数字类型 @Swift

- Int, UInt, Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64
- Float, Float16, Float32, Float64
- Double

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
47 48 49
**特有数字类型的使用场景**

大多数场景下,开发者使用 字面量(即Number类型)就可以满足需要,但是也有需要特有数字类型的场景。
D
DCloud_LXH 已提交
50

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
51 52 53 54 55 56
1. 在 kotlin 和 swift 中,有些系统API或三方SDK的传入和返回强制约定了这些平台特有数字类型,此时无法使用number。
2. number作为泛数字,性能还是弱于Int。在普通计算中无法体现出差异,但在千万次运算后,累计会产生毫秒级速度差异。

当需要特有数字类型时,UTS中可以直接定义<!--,也可以通过number类型转换为特有数字类型。-->

可以使用下面的方法,虽然可能会被编辑器报语法错误(后续HBuilderX会修复这类误报),但编译到 kotlin 和 swift 时是可用的。
D
DCloud_LXH 已提交
57 58

- 声明特定的平台数字类型
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
59
 > 目前这些特有数字类型,声明类型时,与 number 不同的是,均为首字母大写
D
DCloud_LXH 已提交
60 61 62 63 64 65 66 67

```ts

let a:Int = 3 //注意 Int 是首字母大写
let b:Int = 4
let c:Double  = a * 1.0 / b
```

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
68 69 70 71
* 注意这些特有数字类型不能在web端和小程序端使用,如工程需兼容非App端,要把这些代码放入条件编译;
* iOS和Android都有的类型,比如Int,编译后可跨2个平台;但如果使用了某平台专有的数字类型,比如swift的Int8,则此代码不能编译到Android,工程如需支持Android,则把这些代码写在条件编译里。


D
DCloud_LXH 已提交
72 73 74 75 76 77 78 79 80
- 在 kotlin(app-android) 下转换特定的平台数字类型
```ts
let a:Int = 3
a.toFloat() // 转换为 Float 类型,后续也将支持 new Float(a) 方式转换
a.toDouble() // 转换为 Double 类型,后续也将支持 new Double(a) 方式转换
```

- 在 swift(app-ios) 下转换特定的平台数字类型
```ts
lizhongyi_'s avatar
lizhongyi_ 已提交
81 82 83 84 85 86 87
// number转成特定类型
let num = 2
num.toInt() //将number 变量 num 转换为 Int 类型
num.toFloat() //将number 变量 num 转换为 float 类型
num.toInt64() // 将number 变量 num 转换为 Int64 类型

// 特定类型转成其他的特定类型
D
DCloud_LXH 已提交
88 89 90
let a:Int = 3
let b = new Double(a) // 将整型变量 a 转换为 Double 类型
```
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
91 92 93 94

<!-- #### number和特有数字类型互转 -->

#### 边界情况说明:
D
DCloud_LXH 已提交
95 96 97 98 99 100

- 在不同平台上,数值的范围限制不同,超出限制会导致相应的错误或异常
  * 编译至 JavaScript 平台时,最大值为 1.7976931348623157e+308,最小值为 -1.7976931348623157e+308,超出限制会返回 `Infinity``-Infinity`
  * 编译至 Kotlin 平台时,最大值为 9223372036854775807,最小值为 -9223372036854775808,超出限制会报错:`The value is out of range‌`
  * 编译至 Swift 平台时,最大值 9223372036854775807,最小值 -9223372036854775808,超出限制会报错:`integer literal overflows when stored into Int`

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
101 102 103
#### 更多API
number内置对象还有一些API,[详见](buildin-object-api/number.md)

D
DCloud_LXH 已提交
104 105 106 107 108 109 110 111 112 113 114 115 116
### 字符串(String) @String

字符串是一串表示文本值的字符序列,例如:`"hello world"`

边界情况说明:

- 在不同平台上,字符串的长度限制不同,超出限制会导致相应的错误或异常
  * 编译至 JavaScript 平台时,最大长度取决于 JavaScript 引擎,例如在 V8 中,最大长度为 2^30 - 25,超出限制会报错:`Invalid string length`;在 JSCore 中,最大长度为 2^31 - 1,超出限制会报错:`Out of memory __ERROR`
  * 编译至 Kotlin 平台时,最大长度受系统内存的限制,超出限制会报错:`java.lang.OutOfMemoryError: char[] of length xxx would overflow`
  * 编译至 Swift 平台时,最大长度也受系统内存的限制,超出限制目前没有返回信息。

### 日期(Date)@date

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
117
日期对象表示日期,包括年月日时分秒等各种日期。[详见](buildin-object-api/date.md)
D
DCloud_LXH 已提交
118 119 120 121 122 123

### null

一个表明 null 值的特殊关键字。

有时需定义可为null的字符串,可以在类型描述中使用`|`操作符。
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
124

D
DCloud_LXH 已提交
125 126 127 128
```ts
let user: string | null
```

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
129 130 131 132 133 134 135 136 137 138 139 140
> 注意:uts 编译为kotlin和swift时不支持 undefined。每个有类型的变量都需要初始化或赋值。

### 数组(Array)

Array,即数组,支持在单个变量名下存储多个元素,并具有执行常见数组操作的成员。

js的array是可变长的泛型array。

在kotlin中,array是不可变长的,length是固定的。只有arrayList是可变长的。

<!-- 补充swift说明 -->

杜庆泉's avatar
杜庆泉 已提交
141
为了拉齐实现,UTS补充了UTSArray,它继承自ArrayList,所以可以变长。
D
DCloud_LXH 已提交
142

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
143
但为了接近web的写法,方便跨端,UTSArray在new的时候仍使用了`new Array`
杜庆泉's avatar
杜庆泉 已提交
144

杜庆泉's avatar
杜庆泉 已提交
145 146 147 148 149 150 151 152

#### 创建一个数组对象

`UTS`中数组的创建有两种方式:

1 字面量创建

```
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
153 154
let a = [1,2,3];//支持
let a = [1,'2',3];//支持
杜庆泉's avatar
杜庆泉 已提交
155 156

// 需要注意的是,字面量创建的数组,不支持出现空的缺省元素
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
157
let a = [1,,2,3];//不支持
杜庆泉's avatar
杜庆泉 已提交
158 159 160 161
```

2  创建数组对象
```
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
162 163 164 165
let a = new Array(1,2,3);//支持
let a = new Array(1,'2',3);//支持
let a = Array(1,2,3);//支持
let a = Array(1,'2','3');//支持
杜庆泉's avatar
杜庆泉 已提交
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
```

#### 遍历数组对象

在UTS语言中,推荐使用foreach来实现数组的遍历

```
const array1: string[] = ['a', 'b', 'c'];
array1.forEach((element:string, index:number) => {
    console.log(array1[index])
});
```


#### kotlin 平台的Array 特性
杜庆泉's avatar
杜庆泉 已提交
181

杜庆泉's avatar
杜庆泉 已提交
182
在kotlin平台上,Array 的具体实现类为: `io.dcloud.uts.UTSArray` 
杜庆泉's avatar
杜庆泉 已提交
183

杜庆泉's avatar
杜庆泉 已提交
184
UTSArray 拉齐了Web平台 Array的功能和定义,可以满足大多数场景需要 ,但是在涉及与 系统API/三方sdk 交互部分,因为 系统API/三方sdk 是基于 java/kotlin 开发 因此可能会产生类型不一致的错误。
杜庆泉's avatar
杜庆泉 已提交
185 186


杜庆泉's avatar
杜庆泉 已提交
187
举个例子:
杜庆泉's avatar
杜庆泉 已提交
188 189 190 191 192

```uts
let packageManager = UTSAndroid.getUniActivity()!.getPackageManager();
let intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
杜庆泉's avatar
杜庆泉 已提交
193
// 查询当前设备上安装了几个launcher
杜庆泉's avatar
杜庆泉 已提交
194 195 196
let resolveInfo = packageManager.queryIntentActivities(intent,0);
```

杜庆泉's avatar
杜庆泉 已提交
197 198 199 200 201 202 203 204
上面的代码向 系统查询了有多少应用可以响应 `launcher`行为 ,返回的 resolveInfo 是一个 `List<ResolveInfo>`

这种情况下,我们建议的做法是将其先转换为UTSArray对象再进行其他处理和操作

```uts
let launcherList = UTSArray.fromNative(resolveInfo) 
console.log(clothing.length);
```
杜庆泉's avatar
杜庆泉 已提交
205 206 207 208 209 210 211




下面汇总了常用的转换场景和代码:

##### 1 我有一个UTSArray 需要转换为其他类型
杜庆泉's avatar
杜庆泉 已提交
212 213

```
杜庆泉's avatar
杜庆泉 已提交
214
let utsArr= ["hello","world"]
杜庆泉's avatar
杜庆泉 已提交
215 216

// UTSArray 转换 kotlin.collections.List
杜庆泉's avatar
杜庆泉 已提交
217 218
let kotlinList = utsArr.toKotlinList()

杜庆泉's avatar
杜庆泉 已提交
219 220
// UTSArray 转换 kotlin.Array
let kotlinArray = utsArr.toTypedArray()
杜庆泉's avatar
杜庆泉 已提交
221 222 223

```

杜庆泉's avatar
杜庆泉 已提交
224 225 226


##### 2 我有一个原生类数组类型 需要转成一个UTSArray
杜庆泉's avatar
杜庆泉 已提交
227 228

```
杜庆泉's avatar
杜庆泉 已提交
229
// kotlin.collections.List 转换 UTSArray
杜庆泉's avatar
杜庆泉 已提交
230
let utsArr= mutableListOf("hello","world")
杜庆泉's avatar
杜庆泉 已提交
231
let kotlinList = UTSArray.fromNative(utsArr) 
杜庆泉's avatar
杜庆泉 已提交
232 233
```

杜庆泉's avatar
杜庆泉 已提交
234
```
杜庆泉's avatar
杜庆泉 已提交
235
// kotlin.Array 转换 UTSArray
杜庆泉's avatar
杜庆泉 已提交
236
let utsArr= arrayOf("hello","world")
杜庆泉's avatar
杜庆泉 已提交
237
let kotlinList = UTSArray.fromNative(utsArr)
杜庆泉's avatar
杜庆泉 已提交
238 239
```

杜庆泉's avatar
杜庆泉 已提交
240

杜庆泉's avatar
杜庆泉 已提交
241

D
DCloud_LXH 已提交
242 243
### Object类型 @object

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
244
对象(object)是指内存中的可以被标识符引用的一块区域,是一种引用类型。包括Array,Date,Map,Set,JSON等。
D
DCloud_LXH 已提交
245 246 247

### any类型 @any

fxy060608's avatar
fxy060608 已提交
248
有时候,我们会想要为那些在编程阶段还不清楚类型的变量指定一个类型。 这些值可能来自于动态的内容,比如来自用户输入或第三方代码库。 这种情况下,我们不希望类型检查器对这些值进行检查而是直接让它们通过编译阶段的检查。 那么我们可以使用 any 类型来标记这些变量:
D
DCloud_LXH 已提交
249 250

```ts
fxy060608's avatar
fxy060608 已提交
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // okay, definitely a boolean
```

当你只知道一部分数据的类型时,any类型也是有用的。 比如,你有一个数组,它包含了不同的类型的数据:

```ts
let list: any[] = [1, true, "free"];
list[1] = 100;
```

### null类型 @null

uts 的类型系统可以消除来自代码空引用的危险。
许多编程语言中最常见的陷阱之一,就是访问空引用的成员会导致空引用异常。在 Java 中,这等同于 NullPointerException 或简称 NPE。
在 uts 中,类型系统能够区分一个引用可以容纳 null (可空引用)还是不能容纳(非空引用)。 例如,String 类型的常规变量不能容纳 null:

```ts
let a: string = "abc" // 默认情况下,常规初始化意味着非空
a = null // 编译错误
```

如果要允许为空,可以声明一个变量为可空字符串(写作 string | null):

```ts
let b: string | null = "abc" // 可以设置为空
b = null // ok
```

现在,如果你调用 a 的方法或者访问它的属性,它保证不会导致 NPE,这样你就可以放心地使用:

```ts
const l = a.length
```

但是如果你想访问 b 的同一个属性,那么这是不安全的,并且编译器会报告一个错误:

```ts
const l = b.length // 错误:变量“b”可能为空
```

但是,还是需要访问该属性,对吧?有几种方式可以做到。


#### 在条件中检测 null

首先,你可以显式检测 b 是否为 null:

```ts
if (b != null) {
  console.log(b.length)
}
```

编译器会跟踪所执行检测的信息,并允许你在 if 内部调用 length。

#### 安全的调用

访问可空变量的属性的第二种选择是使用安全调用操作符 ?.:

```ts
const a = "uts"
const b: string | null = null
console.log(b?.length)
console.log(a?.length) // 无需安全调用
```

如果 b 非空,就返回 b.length,否则返回 null,这个表达式的类型是 number | null。

安全调用在链式调用中很有用。例如,一个员工 Bob 可能会(或者不会)分配给一个部门。 可能有另外一个员工是该部门的负责人。获取 Bob 所在部门负责人(如果有的话)的名字, 写作:

```ts
bob?.department?.head?.name
```

如果任意一个属性(环节)为 null,这个链式调用就会返回 null。

#### 空值合并

空值合并运算符(??)是一个逻辑运算符,当左侧的操作数为 null 时,返回其右侧操作数,否则返回左侧操作数。

```ts
const foo = null ?? 'default string';
console.log(foo);
// Expected output: "default string"

const baz = 0 ?? 42;
console.log(baz);
// Expected output: 0
```

#### 非空断言

非空断言运算符(!)将任何值转换为非空类型。可以写 b! ,这会返回一个非空的 b 值(例如:在我们示例中的 String)或者如果 b 为 null,就会抛出一个异常。

```ts
const l = b!.length
D
DCloud_LXH 已提交
349
```