第4章 ArkTS语言基础(上):语法概览、变量声明与数据类型
好,咱们正式开始接触ArkTS了。说实话,很多从Java或标准TypeScript转过来的朋友,第一眼看到ArkTS会觉得「有点怪」。嗯,我当初也是这个感觉。但用了一段时间后,你会发现它其实是在帮你规避一些容易踩坑的写法。
这一章我们先打地基。把语法概览、变量声明、基础数据类型和函数定义这几个核心点讲透。你想想看,地基打不牢,后面写复杂页面和业务逻辑的时候,debug能把你搞疯。
4.1 ArkTS语法概览:它到底「严」在哪?
ArkTS是TypeScript的超集,但做了严格的静态类型约束。说白了,它不允许你随心所欲地写JS那种「爱啥类型就啥类型」的代码。
核心原则就两条:
- 类型必须明确:变量、参数、返回值,都得说清楚是什么类型。
- 运行时行为可预测:不允许隐式类型转换,减少运行时意外。
我在项目中遇到过最典型的例子:有个同事从JS转过来,写了个 let count = "5" + 3,在JS里结果是 "53",但在ArkTS里直接编译报错。为什么?因为类型不匹配。ArkTS不允许string和number直接相加。这种严格其实是在保护你,避免线上出现诡异的bug。
重要认知: ArkTS不是「阉割版」的TS,而是「安全增强版」。它去掉了一些容易出问题的动态特性,换来了更好的编译期检查和性能优化空间。
4.2 变量声明:let 和 const 怎么选?
在ArkTS里,声明变量只有两个关键字:let 和 const。没有 var,这一点跟现代TS保持一致。
我的选择原则很简单:
- 默认用
const:只要这个变量在初始化后不需要重新赋值,就用const。这能避免很多意外修改。 - 只有明确需要重新赋值时,才用
let:比如循环计数器、累加器这类场景。
我曾经在一个项目里看到有人把所有变量都声明成 let,结果一个函数里变量被改了七八次,最后查bug查了整整一下午。从那以后,我团队里就定了个规矩:能用const绝不用let。
个人习惯: 我写ArkTS代码时,会先写const,如果编译报错说「不能赋值给常量」,再改成let。这样能强制自己思考「这个变量真的需要变吗?」
看个例子:
// 推荐写法
const userName: string = "张三";
const maxRetryCount: number = 3;
// 需要重新赋值的场景
let currentIndex: number = 0;
for (let i = 0; i < 10; i++) {
currentIndex = i;
}
4.3 基础数据类型:string, number, boolean
这三个是最常用的基础类型。没什么花哨的,但有几个细节要注意。
string(字符串)
支持单引号、双引号和模板字符串。我个人偏爱模板字符串,因为拼接变量时最直观。
const firstName: string = "李";
const lastName: string = "四";
// 模板字符串,用反引号
const fullName: string = `${firstName}${lastName}`;
console.log(fullName); // 输出:李四
注意: ArkTS里字符串是不可变的。你没法通过索引修改某个字符。比如 str[0] = 'a' 这种操作是不允许的。想修改?重新生成一个新字符串吧。
number(数字)
ArkTS里只有一种数字类型:number。它涵盖整数和浮点数。没有Java里那种int、float、double的区分。
const age: number = 25;
const price: number = 19.99;
const hexValue: number = 0xFF; // 十六进制也支持
我记得有个新手问我:「为什么我算钱的时候,0.1 + 0.2 不等于 0.3?」嗯,这是所有编程语言都有的浮点数精度问题。ArkTS也不例外。如果你要做精确的金额计算,建议用整数(分)来算,或者用专门的库。
boolean(布尔值)
只有 true 和 false 两个值。注意,ArkTS里不会做隐式类型转换。你不能写 if (1) 这种代码,必须写成 if (1 === 1) 或者 if (true)。
const isLoggedIn: boolean = false;
// 正确写法
if (isLoggedIn === true) {
// 执行逻辑
}
// 错误写法(编译报错)
// if (isLoggedIn) { } // 这样写其实可以,但为了清晰,我建议显式比较
避坑指南: 我曾经在条件判断里直接写 if (someString),在JS里空字符串会被当作false。但在ArkTS里,这种写法虽然能编译通过,但语义不清晰。我后来统一改成 if (someString.length > 0),代码可读性提升了一大截。
4.4 复合数据类型:array 和 object
基础类型只能存单个值。要存一组数据,就得用数组和对象。
array(数组)
数组有两种声明方式。我个人推荐使用泛型写法,更清晰。
// 方式一:泛型写法(推荐)
const names: Array<string> = ["张三", "李四", "王五"];
// 方式二:简写语法
const ages: number[] = [25, 30, 35];
// 混合类型?不行!ArkTS要求数组元素类型一致
// const mixed: Array<string | number> = ["hello", 123]; // 联合类型可以,但别滥用
数组的操作方法和标准JS一样:push、pop、forEach、map 等都能用。但注意,如果你声明的是 const 数组,你不能重新赋值整个数组,但可以修改数组里的元素。
const fruits: string[] = ["苹果", "香蕉"];
fruits.push("橘子"); // 可以,修改内容
// fruits = ["西瓜"]; // 报错!不能重新赋值
object(对象)
对象在ArkTS里需要定义结构。你可以用接口(interface)或类型别名(type)来约束对象的形状。
// 先定义接口
interface User {
id: number;
name: string;
isVIP: boolean;
}
// 然后创建对象
const user: User = {
id: 1,
name: "赵六",
isVIP: true
};
// 访问属性
console.log(user.name); // 赵六
我的经验: 定义对象时,一定要先写接口或类型。别偷懒直接写 const obj = {} 然后往里塞属性。ArkTS的静态检查会帮你发现拼写错误和类型不匹配。我见过太多因为属性名写错导致的bug了。
4.5 函数定义:从基础到进阶
函数是ArkTS里组织逻辑的基本单元。写法上跟TS很像,但约束更严格。
基本函数定义
必须指定参数类型和返回值类型。如果函数没有返回值,用 void。
// 有返回值
function add(a: number, b: number): number {
return a + b;
}
// 无返回值
function logMessage(msg: string): void {
console.log(msg);
// 没有 return 语句
}
可选参数和默认参数
参数可以设为可选(加问号),也可以给默认值。
// 可选参数
function greet(name: string, greeting?: string): string {
if (greeting) {
return `${greeting}, ${name}`;
}
return `你好, ${name}`;
}
// 默认参数
function createUser(name: string, age: number = 18): object {
return { name, age };
}
console.log(createUser("小明")); // { name: '小明', age: 18 }
注意: 可选参数必须放在必选参数后面。这是语法规定,也是常识——你想想看,如果可选参数在前面,调用时传参顺序就乱套了。
箭头函数(Lambda表达式)
箭头函数在ArkTS里非常常用,尤其是在回调场景。写法简洁,而且不绑定自己的 this。
// 传统函数
const double1 = function(n: number): number {
return n * 2;
};
// 箭头函数(推荐)
const double2 = (n: number): number => n * 2;
// 多行箭头函数
const processData = (data: string[]): number => {
const filtered = data.filter(item => item.length > 3);
return filtered.length;
};
我记得刚开始用箭头函数时,总觉得语法别扭。但用顺手之后,发现它特别适合用在数组的 map、filter 方法里,代码一下子简洁了很多。
函数作为参数(回调函数)
ArkTS里函数是一等公民,可以像变量一样传递。
// 定义回调类型
type Callback = (result: string) => void;
// 接受回调的函数
function fetchData(url: string, onSuccess: Callback): void {
// 模拟网络请求
const data = "模拟数据";
onSuccess(data);
}
// 调用时传入箭头函数
fetchData("https://api.example.com", (result) => {
console.log("获取到数据:", result);
});
核心要点: 函数定义时,参数类型和返回值类型必须写清楚。这不仅是语法要求,更是文档。三个月后你回头看自己的代码,类型声明就是最好的注释。
4.6 本章小结
这一章我们覆盖了ArkTS最基础但最重要的几个概念:
- 语法风格:严格静态类型,不允许隐式转换
- 变量声明:优先用
const,必要时用let - 基础类型:string、number、boolean,注意精度和不可变性
- 复合类型:数组元素类型一致,对象要定义接口
- 函数定义:类型明确,善用箭头函数和回调
这些内容看起来简单,但它们是后面所有复杂逻辑的基石。下一章我们会深入讲联合类型、类型别名和泛型,那才是真正体现ArkTS威力的地方。
嗯,先消化这些。有任何疑问,欢迎在课程群里讨论。咱们下章见。