鸿蒙,ArkTs 一段诡异的代码
分享一段我之前在学习 ArkTs 的时候,看到的一段诡异的代码。我们来看看下面的代码,按照你多年的经验,分析一下下面的代码是否可以正常执行,如果可以执行的话,能说出运行结果吗。
for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
以上代码是可以正常运行的,这段代码的执行结果,将会输出了 3 个 'abc'
:
abc
abc
abc
这段代码中的 for
循环尝试执行三次循环,每次循环中都声明了一个新的局部变量 i
,并将其赋值为字符串 'abc'
。然后,它打印出这个新的局部变量 i
。
在每次迭代中,尽管外部循环的控制变量也叫 i
,但内部的 let i = 'abc';
实际上创建了一个新的、同名的局部变量 i
,这个变量的作用域仅限于 for
循环的块内部。因此,每次迭代打印的都是这个块作用域内的字符串 'abc'
,而不是外部循环控制变量的数值。
从执行结果也能间接说明,for 循环内部声明的变量 i
和循环变量 i
不在同一个作用域,它们有各自单独的作用域,设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域,这是 for 循环的特别之处。
如果在同一个作用域,是不可使用 let 或者 const 重复声明相同名字的变量。比如下面的代码会报错。
if(true){
let a = 1;
let a = 2; // 报错
const b = 3;
const b = 4; // 报错
}
这就引发出了另外一问题 块作用域。
块作用域是指变量在定义它的代码块或者说是大括号 {}
内有效的作用域。使用 let
或者 const
关键字声明的变量具有块级作用域(block scope),这意味着变量在包含它的块(在这个例子中是 for
循环的大括号内)以及任何嵌套的子块中都是可见的。
块作用域示例:
let blockScopedVariable = 'I am dhl';
if (true) {
let blockScopedVariable = 'I am block scoped';
console.log(blockScopedVariable); // 输出: I am block scoped
}
console.log(blockScopedVariable); // 输出: I am dhl
从执行结果可以看出,在 if
语句中定义的变量 blockScopedVariable
,仅在代码块内有效,外层变量不会被内层同名变量的声明和赋值影响。
但是需要注意,在 ArkTS 中不能使用 for .. in
,否则会有一个编译警告。
之所以不能使用 for .. in
是因为在 ArkTS 中,对象的布局在编译时是确定的,且不能在程序执行期间更改对象的布局,换句话说,ArkTS 禁止以下行为:
- 向对象中添加新的属性或方法
- 从对象中删除已有的属性或方法
- 将任意类型的值赋值给对象属性
如果修改对象布局会影响代码的可读性以及运行时性能。
从开发的角度来说,在某处定义类,然后又在其它地方修改了实际对象布局,这很容易引入错误,另外如果修改对象布局,需要在运行时支持,这样会增加执行开销降低性能。
来源:juejin.cn/post/7376158566598705167