提交 d56080da 编写于 作者: D DCloud_LXH

chore: USTJSONObject -> UTSJSONObject

上级 f3c04e78
# 类型@data-type
强类型语言的特点,是数据类型要求严格。它带来2个好处:
1. 高性能:明确的类型有更大的优化空间,在iOS和Android等os上可以节省内存、提高运算速度;web端由于仍编译为js,不具有类型性能优化。
2. 安全的代码:强类型代码编写虽然没有弱类型自由,但类型检查、非空检查...各种检查可以提升代码的健壮性。
1. 高性能:明确的类型有更大的优化空间,在iOS和Android等OS上可以节省内存、提高运算速度;web端由于仍编译为js,不具有类型性能优化。
2. 安全的代码:强类型代码编写虽然没有弱类型自由,但类型检查、非空检查...等各种检查可以提高代码的健壮性。
如果您是js开发者,那么需要一定的学习过程来掌握 UTS 的类型系统。总体原则是你将牺牲一些代码的灵活性,来换取代码的健壮性和高性能。
......@@ -11,8 +11,8 @@
比如 `"abc"``"你好"`,都属于字符串string,所有string类型有相同的方法、属性,比如`.length`属性获取字符串长度。
UTS 的类型有:
- 基础类型:boolean、number、string、any、null,都是小写前3个typeof返回类型名称,null的typeof是object,any的typeof是运行时值的类型。
- 对象类型:Date、Array、Map、Set、USTJSONObject,首字母大写,typeof返回"object",判断准确类型需使用 instanceof
- 基础类型:boolean、number、string、any、null,都是小写前3个typeof返回类型名称,null的typeof是object,any的typeof是运行时值的类型。
- 对象类型:Date、Array、Map、Set、UTSJSONObject,首字母大写。typeof返回"object",判断准确类型需使用 instanceof
- 使用 type 来自定义类型
- 特殊类型:function、class、error。
- 平台专有类型:Int、Float、Double、NSString、kotlin.Array...
......@@ -30,7 +30,7 @@ let c:boolean // 定义类型但定义时未赋值
c = true // 后续为变量赋值字面量
```
注意:
**注意:**
- 在js里,true == 1、 false == 0。但在其他强类型语言里,`1``0`是数字类型,无法和布尔类型相比较。
- 注意 boolean 不要简写成 bool
......@@ -112,8 +112,8 @@ number本身的使用很简单,但混入了平台专有数字类型后,会
- Swift 中 Int 类型是根据平台动态的,在 32 位设备下等同于 Int32, 在64位设备下等同于 Int64。因此建议整型使用 Int, 除非必要,且在保证不会溢出的场景下才使用 Int32、Int64。
- 同样,Swift 中的 UInt 类型也是根据平台动态的,在 32 位设备下等同于 UInt32, 在64位设备下等同于 UInt64。建议使用 UInt,非必要不使用 UInt32、UInt64。
- Float16 在 iOS14.0 及以上系统上才能使用,使用时注意做系统版本号判断。[参考](../plugin/uts-uni-api.md#设备)
- Float32 是 Float 的 typealise, 两者等价。
- Float64 是 Double 的 typealise, 两者等价。
- Float32 是 Float 的类型别名, 两者等价。
- Float64 是 Double 的类型别名, 两者等价。
#### 专有数字类型的定义方式
......@@ -188,8 +188,8 @@ let a:Int = 1 // 类型为Int
`let b:Int = 1/10` 会在 HBuilderX 3.9+起报错,原因见下面第二条规则。
再澄清下规则1:
* 如果定义变量时已经显式声明了类型,和规则1无关
* 如果不是定义变量,和规则1无关
* 如果定义变量时已经显式声明了类型,和规则1无关
* 如果不是定义变量,和规则1无关
也就是如下代码中,`60`这个字面量的处理,和规则1无关,不会把这个`60`改为number类型
......@@ -218,7 +218,7 @@ test(1/10) // 报错,类型不匹配。需要number而传入Int
这里的`纯数字字面量的除法`,指除法表达式中除了数字和运算符,不包括任何其他东西:
- 比如变量:`let a:Int=1;let b:Int= a/1`
- 比如被as过`(1 as Int)/10`
- 比如使用 as 断言`(1 as Int)/10`
以上除法表达式,都不是“纯数字字面量的除法”,都不会被推导为number。
但是这条规则,也会导致一个**向下兼容问题**
......@@ -251,19 +251,19 @@ test((1.0 as Double)/10) //表达式中任意一个数字as一下,都不会走
所有的 number 都支持下列方法进行转换(部分类库API使用java编写,其要求的java类型与下列kotlin类型完全一致,可以直接使用
* toByte(): Byte
* toShort(): Short
* toInt(): Int
* toLong(): Long
* toFloat(): Float
* toDouble(): Double
* toByte(): Byte
* toShort(): Short
* toInt(): Int
* toLong(): Long
* toFloat(): Float
* toDouble(): Double
另外 number 还具备下列函数进行整型的无符号转换,这部分API 在jvm上没有对应的原始数据类型,主要的使用场景是 色值处理等专业计算场景的`多平台拉齐`
* toUByte(): UByte
* toUShort(): UShort
* toUInt(): UInt
* toULong(): ULong
* toUByte(): UByte
* toUShort(): UShort
* toUInt(): UInt
* toULong(): ULong
```ts
let a:number = 3
......@@ -711,60 +711,62 @@ let kotlinArray = utsArr.toTypedArray()
#### iOS 平台专有数组类型
UTS 中的 Array 对应到 Swift 中就是 Array, 方法是通用的,无需转换。一般情况下,使用 Array 即可。
但是,某些系统或者三方库 API 可能会要求 OC 的 NSArray、NSMutableArray 类型的数组,这个时候就需要进行转换。
>UTS 中的 Array 对应到 Swift 中就是 Array, 方法是通用的,无需转换。一般情况下,使用 Array 即可。
>
>但是,某些系统或者三方库 API 可能会要求 OC 的 NSArray、NSMutableArray 类型的数组,这个时候就需要进行转换。
- 专有数组类型清单
* NSArray
* NSMutableArray
- 专有数组类型定义方式
1. 创建 NSArray
NSArray 是 OC 中的不可变数组,顾名思义,数组创建完成之后就不可以再添加或者删除元素。因此,创建 NSArray 对象时就应该完成数组的初始化。
可以通过以下方式创建 NSArray:
```ts
// 方式一: 创建一个空数组,注意数组创建后就不可改变,不能再添加或者删除元素,应避免使用该方式。
let a: NSArray = NSArray()
// 方式二: 用一个数组创建一个 NSArray, 推荐使用。同样,创建完成后数组不可变。
let b: NSArray = NSArray(array=[1, 2, 3, 4]) // 等价于 any[],注意:不是等价于 number[]
// 方式三: 用一个元素定义 NSArray, 不推荐使用
let c: NSArray = NSArray(object=1)
// 方式四:用不定长元素定义 NSArray, 可以使用
let d: NSArray = NSArray(objects=1, "2", false, "ok")
```
> NSArray 是 OC 中的不可变数组,顾名思义,数组创建完成之后就不可以再添加或者删除元素。因此,创建 NSArray 对象时就应该完成数组的初始化。可以通过以下方式创建 NSArray:
```ts
// 方式一: 创建一个空数组,注意数组创建后就不可改变,不能再添加或者删除元素,应避免使用该方式。
let a: NSArray = NSArray()
// 方式二: 用一个数组创建一个 NSArray, 推荐使用。同样,创建完成后数组不可变。
let b: NSArray = NSArray(array=[1, 2, 3, 4]) // 等价于 any[],注意:不是等价于 number[]
// 方式三: 用一个元素定义 NSArray, 不推荐使用
let c: NSArray = NSArray(object=1)
// 方式四:用不定长元素定义 NSArray, 可以使用
let d: NSArray = NSArray(objects=1, "2", false, "ok")
```
2. 创建 NSMutableArray
NSMutableArray 是 OC 中的可变数组,其是 NSArray 的子类,可变数组创建后可以增加或者删除元素。NSArray 的所有创建方式也都适用于 NSMutableArray
```ts
// 方式一: 创建一个空数组,其类型等价于 any[]
let a: NSMutableArray = NSMutableArray()
a.add(1) //添加一个元素
a.add("22") //添加一个元素
a.add(false) //添加一个元素
a.remove(1) //移除一个元素
a.removeObject(at=2) //移除一个指定下标的元素
a.removeAllObjects() //移除全部元素
a.removeLastObject() //移除最后一个元素
// 方式二: 用一个数组创建一个 NSMutableArray, 推荐使用。
let b: NSMutableArray = NSMutableArray(array=[1, 2, 3, 4]) // 等价于 any[],注意:不是等价于 number[]
// 方式三: 用一个元素定义 NSMutableArray
let c: NSMutableArray = NSMutableArray(object=1)
// 方式四:用不定长元素定义 NSMutableArray
let d: NSMutableArray = NSMutableArray(objects=1, "2", false, "ok")
```
- NSMutableArray 是 OC 中的可变数组,其是 NSArray 的子类,可变数组创建后可以增加或者删除元素。NSArray 的所有创建方式也都适用于 NSMutableArray
```ts
// 方式一: 创建一个空数组,其类型等价于 any[]
let a: NSMutableArray = NSMutableArray()
a.add(1) //添加一个元素
a.add("22") //添加一个元素
a.add(false) //添加一个元素
a.remove(1) //移除一个元素
a.removeObject(at=2) //移除一个指定下标的元素
a.removeAllObjects() //移除全部元素
a.removeLastObject() //移除最后一个元素
// 方式二: 用一个数组创建一个 NSMutableArray, 推荐使用。
let b: NSMutableArray = NSMutableArray(array=[1, 2, 3, 4]) // 等价于 any[],注意:不是等价于 number[]
// 方式三: 用一个元素定义 NSMutableArray
let c: NSMutableArray = NSMutableArray(object=1)
// 方式四:用不定长元素定义 NSMutableArray
let d: NSMutableArray = NSMutableArray(objects=1, "2", false, "ok")
```
- 专有数组类型 转 Array
```ts
......@@ -797,11 +799,11 @@ let a3: NSMutableArray = NSMutableArray(array= a)
```
- 注意:
+ 无论是 NSArray 还是 NSMutableArray 对象创建后都等价于 any[] 类型的数组,此时 Swift 不再有类型推导,可以往可变数组中添加任意类型的非空元素。
+ NSArray 和 NSMutableArray 类型的数组不接受空值 null, 任何情况下不要往这两种类型中注入 null。 否则,在运行时可能会引起应用闪退。
+ Array 类型不能通过 as 方式转换成 NSMutableArray 类型。 但是可以通过 as 方式 转换成 NSArray 类型。
+ Swift 中的 Array 是值类型,其和 TS 中 Array 的一点区别是 可以通 == 判断两个数组是否相等,只要两个数组的类型和元素一样,判等的结果就是 true。
**注意:**
+ 无论是 NSArray 还是 NSMutableArray 对象创建后都等价于 any[] 类型的数组,此时 Swift 不再有类型推导,可以往可变数组中添加任意类型的非空元素。
+ NSArray 和 NSMutableArray 类型的数组不接受空值 null, 任何情况下不要往这两种类型中注入 null。 否则,在运行时可能会引起应用闪退。
+ Array 类型不能通过 as 方式转换成 NSMutableArray 类型。 但是可以通过 as 方式 转换成 NSArray 类型。
+ Swift 中的 Array 是值类型,其和 TS 中 Array 的一点区别是 可以通 == 判断两个数组是否相等,只要两个数组的类型和元素一样,判等的结果就是 true。
### 更多API
......@@ -820,7 +822,7 @@ Map 是一种 key value 形式的数据类型。
//定义一个map1,key为string类型,value也是string类型
const map1: Map<string,string> = new Map();
map1.set('key1', "abc");
console.log(map1.get('key1') //返回 abc
console.log(map1.get('key1')) //返回 abc
//定义一个map1,key为number类型,value是Map类型
const map2: Map<number,Map<string,string>> = new Map();
......@@ -831,7 +833,9 @@ console.log(map2.get(1)?.get("key1")); //返回 abc。因为名为1的key不一
注意在HBuilderX中console.log一个Map时,返回内容格式如下:
```sh
[Object] Map(3) {"sex":0,"name":"zhangsan","age":12} at pages/index/index.uvue:60
```
开头的[Object]代表其typeof的类型,Map代表它的实际类型,(3)是map的size,{...} 是Map的内容。
......@@ -855,7 +859,7 @@ console.log(map1 instanceof Map); //返回 true
Map对象还有很多API,delete、clear等,[详见](buildin-object-api/map.md)
## USTJSONObject@ustjsonobject
## UTSJSONObject@utsjsonobject
json 在 js 中并非一个独立的类型,对一个 json 对象 typeof 返回的是 object。
......@@ -864,13 +868,13 @@ json 在 js 中用起来很自由,但在强类型语言中,不管kotlin、sw
1. json对象里的每个属性,都需要定义类型
2. 每个可为空的属性,都需要加`?.`,才能安全读写
一般其他强类型语言的用法,是把json数据内容,转为class、interface或type。然后就可以`.`了。
一般其他强类型语言的用法,是把json数据内容,转为class、interface或type。然后就可以使用`.`来访问了。
在 uts 中使用 JSON,有3种方式:
1. 把 json数据转 type,变成一个自定义类型。这不是本章节的内容,详见 [type](#type)
2. uts 新增了 UTSJSONObject 对象,可以把 json数据通过字面量赋值 或 JSON.parse()方式,赋值给 uts 内置的 UTSJSONObject 对象。
3. 由于 USTJSONObject有toMap()方法,所以也可以转为Map后使用json数据。
3. 由于 UTSJSONObject有toMap()方法,所以也可以转为Map后使用json数据。
UTSJSONObject,是一个类型,可以在变量的冒号后面使用,本节的重点就是介绍UTSJSONObject。
......@@ -934,7 +938,7 @@ let jo2 = {
关于属性名是否需要使用引号包围的规则:
1. 如果是对象字面量赋值,普通属性名称无需使用引号包围,但使用也没问题
2. 如果是对象字面量赋值,且属性名包括`-`,则必须两侧加引号包围。
2. 如果是对象字面量赋值,且属性名包括特殊符号,如:`-`,则必须两侧加引号包围。
3. 如果是JSON.parse()方法入参需要的字符串,则属性名必须使用双引号包围(web端规则也是如此)
如果开发者不想搞明白这些细节,可以简单粗暴的都给属性名都加上引号。
......@@ -1011,14 +1015,14 @@ let rect = {
以上述 rect 为例,访问 UTSJSONObject 中的数据,有如下3种方式:
1. `.`操作符
1. `.` 操作符
`rect.x``rect.size.width`
这种写法比较简单,和js习惯一致,但在 UTS 中限制较多。它的使用有如下前提:
- 仅限于web和Android,在iOS上swift不支持`.`操作符。
- 在Android上也只支持字面量定义json(因为类型可推导)。如果是`JSON.parse()`转换的,则不能使用。
2. [""]下标属性
2. `[""]` 下标属性
`rect["x"]`
这是一种通用的方式,不管通过字面量定义的 UTSJSONObject,还是通过 `JSON.parse()`,不管是 web、Android、iOS 哪个平台,都可以使用下标方式访问 UTSJSONObject 属性。
......@@ -1066,17 +1070,19 @@ console.log(listArr[0]["title"]); //第一组
多层级下标访问时需要使用 as 转换为 UTSJSONObject
```ts
var j = {"test":{
"a-b": 1
}}
var j = {
"test":{
"a-b": 1
}
}
console.log((j['test'] as UTSJSONObject)['a-b']);
```
3. 通过 keyPath 访问 UTSJSONObject 数据
1. 通过 keyPath 访问 UTSJSONObject 数据
`HBuilderX` 3.9.0 之后的版本,UTSJSONObject 提供了另外一种属性访问方式,keyPath。如果你了解 XPath、JSONPath 的话,这个概念类似。
kyepath是把`.`操作符作为一个字符串传入了UTSJSONObject的一个方法中,比如`utsObj.getString("address.detailInfo.street")`
keypath是把`.`操作符作为一个字符串传入了UTSJSONObject的一个方法中,比如`utsObj.getString("address.detailInfo.street")`
相对于受限制`.`和需要经常as的下标,更推荐使用keyPath方式来操作UTSJSONObject。
......@@ -1246,14 +1252,15 @@ console.log(personList[1].age); //null
### 嵌套
json对象往往有嵌套,即子对象。比如
```json
{
id: 1,
name: "zhangsan",
age: 18
address: {
city: "beijing",
street: "dazhongsi road"
"id": 1,
"name": "zhangsan",
"age": 18,
"address": {
"city": "beijing",
"street": "dazhongsi road"
}
}
```
......@@ -1263,9 +1270,9 @@ json对象往往有嵌套,即子对象。比如
```ts
type PersonType = {
id: number,
name: string,
name: string,
age: number,
address: { // 错误,这里的address需要单独声明类型
address: { // 错误,这里的address需要单独声明类型
city : string,
street : string
}
......@@ -1276,14 +1283,14 @@ type PersonType = {
```ts
type PersonAddressType = {
city: string,
city: string,
street: string
}
type PersonType = {
id: number,
name: string,
name: string,
age: number,
address: PersonAddressType // 把address定义为PersonAddress类型
address: PersonAddressType // 把address定义为PersonAddress类型
}
```
......@@ -1292,14 +1299,14 @@ type PersonType = {
那么嵌套的完整写法例子:
```ts
type PersonAddressType = {
city: string,
city: string,
street: string
}
type PersonType = {
id: number,
name: string,
name: string,
age: number,
address: PersonAddressType // 把address定义为PersonAddress类型
address: PersonAddressType // 把address定义为PersonAddress类型
}
let person = {
id: 1,
......@@ -1346,12 +1353,20 @@ console.log(person?.name); // 返回zhangsan。由于person可能为null,pars
注意上述代码中,如果`let person`时,想使用冒号定义类型,需要考虑parse失败的情况,要这么写:
```ts
type PersonType = {
id: number,
name: string
}
let person:PersonType|null = JSON.parse<PersonType>(jsonString)
console.log(person?.name); // 返回zhangsan
```
或者如果你确保jsonString的值一定是合法的、parse一定可以成功,那么也可以在定义的末尾!号断言,告诉编译器肯定没有问题,那么此后就可以不使用`?.`
```ts
type PersonType = {
id: number,
name: string
}
let person:PersonType = JSON.parse<PersonType>(jsonString)!
console.log(person.name); // 返回zhangsan
```
......@@ -1373,11 +1388,11 @@ HBuilderX 3.9起内置了一个json转type工具,在`json编辑器`中选择
### 为vue的data中的json定义类型
uvue文件中data中的json数据也涉及类型定义。此时注意:type定义必须放在`export default {}`前面。
```ts
```html
<script>
type PersonType = {
id: number,
name: string
name: string
}
export default {
data() {
......@@ -1405,7 +1420,7 @@ uvue文件中data中的json数据也涉及类型定义。此时注意:type定
// 注意给data定义type,要写在export default的上面
type PersonType = {
id: number,
name: string,
name: string,
age: number,
}
export default {
......
......@@ -160,7 +160,7 @@ const coffees = ["French Roast", "Colombian", "Kona"]
在JS中,对象字面值是封闭在花括号对`{}`中的一个对象的零个或多个“属性名—值”对的(元素)列表。
在uts中,对象字面量赋值给变量,默认会被推导为[UTSJSONObject](data-type.md#USTJSONObject)类型。
在uts中,对象字面量赋值给变量,默认会被推导为[UTSJSONObject](data-type.md#UTSJSONObject)类型。
```ts
// 创建对象
......
......@@ -301,7 +301,7 @@ a as string // 正常
1.0 as number
// 对象字面量也可以as为USTJSONObject或某个type
{"id":1} as USTJSONObject
{"id":1} as UTSJSONObject
type t = {
id:number
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册