鸿蒙开发05-ArkTS中的箭头函数和闭包并和其他语言比较
闭包是指有权访问另一个函数作用域中变量的函数。即使该外部函数执行完毕,其作用域内的变量也不会被销毁,因为闭包持有对这些变量的引用。
一、箭头函数(又名Lambda函数)
定义与语法:箭头函数是 ArkTS 里定义函数的一种简洁方式,它借鉴了 ES6 箭头函数的语法。其基本语法根据参数数量和函数体复杂度有所不同。
无参数时,用空括号 () 表示参数列表,后跟 => 和函数体。例如:
const sayHi = () => console.log('Hi!');
单个参数时,可省略括号,直接写参数名,再跟 => 和函数体。比如:
const square = num => num * num;
多个参数时,用括号包裹参数列表,再跟 => 和函数体。若函数体有多条语句,需用花括号 {} 包裹,且有返回值时要用 return 关键字。示例如下:
const addAndMultiply = (a, b, multiplier) => {
const sum = a + b;
return sum * multiplier;
};
this 指向:箭头函数没有自己的 this,它的 this 值继承自外层函数。这意味着无论箭头函数在何处被调用,其 this 都和外层函数的 this 保持一致。例如:
class MyClass {
value = 10;
getValue = () => this.value;
}
const myObject = new MyClass();
console.log(myObject.getValue());
二、闭包
定义与原理:闭包是指有权访问另一个函数作用域中变量的函数。即使该外部函数执行完毕,其作用域内的变量也不会被销毁,因为闭包持有对这些变量的引用。
function outerFunction() {
const outerVariable = '外部变量';
function innerFunction() {
console.log(outerVariable);
}
return innerFunction;
}
const closure = outerFunction();
closure();
应用场景:主要用于实现数据的封装和隐藏,创建函数的私有变量和方法。比如实现一个计数器:
function counter() {
let count = 0;
return {
increment: () => {
count++;
return count;
},
decrement: () => {
count--;
return count;
}
};
}
const myCounter = counter();
console.log(myCounter.increment());
console.log(myCounter.decrement());
三、对比 ArkTS 箭头函数、ArkTS 闭包、C++ Lambda、Swift 闭包、OC Block
3.1 相同点
功能用途:它们都提供了一种简洁的方式来定义匿名函数,并且都能够捕获外部作用域的变量,可用于实现回调函数、事件处理等功能,使代码更加灵活和简洁。
可作为参数传递:在各自的语言环境中,它们都可以作为函数的参数进行传递,方便实现各种复杂的编程逻辑。
3.2 不同点
3.2.1 语法结构
-
ArkTS 箭头函数:语法简洁,根据参数数量和函数体复杂度有不同写法,依赖于 JavaScript 箭头函数的语法规则。
-
ArkTS 闭包:没有特定的语法格式,是在函数嵌套时自然形成,通过内部函数引用外部函数的变量来实现。
-
C++ Lambda:语法为 捕获列表 -> 返回类型 {函数体},捕获列表用于指定对外部变量的捕获方式,如值捕获、引用捕获等。例如:
#include <iostream> int main() { int a = 10; auto lambda = [a](int b) { return a + b; }; std::cout << lambda(5) << std::endl; return 0; } -
Swift 闭包:语法格式为 { (参数列表) -> 返回类型 in 函数体},有多种参数捕获方式,可通过捕获列表指定对外部变量的捕获行为。例如:
let numbers = [1, 2, 3] let squaredNumbers = numbers.map { $0 * $0 } -
Objective - C Block:语法为 ^返回类型(参数列表) {函数体},定义和使用时需要特定的类型声明,并且要注意内存管理和循环引用问题。例如:
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { int (^add)(int, int) = ^(int a, int b) { return a + b; }; NSLog(@"%d", add(3, 4)); } return 0; }
3.2.2 this/self 指向及捕获
-
ArkTS 箭头函数:this 继承自外层函数,指向固定,不会因为调用方式改变。
-
ArkTS 闭包:普通函数形式的闭包有自己的 this,this 指向取决于函数的调用方式。
-
C++ Lambda:通过捕获列表捕获 this 指针,捕获后可在 Lambda 内部使用对象成员。例如:
class MyClass { public: int value = 10; void func() { auto lambda = [this]() { return this->value; }; std::cout << lambda() << std::endl; } }; -
Swift 闭包:在闭包内使用 self 需明确指定,为避免循环引用,常使用 [weak self] 或 [unowned self]。例如:
class MyClass { var value = 10 func getValue() { let closure = { [weak self] in if let strongSelf = self { print(strongSelf.value) } } closure() } } -
Objective - C Block:在 Block 内使用 self 也需注意循环引用,可使用 __weak 修饰符。例如:
@interface MyClass : NSObject @property (nonatomic, assign) int value; @end @implementation MyClass - (void)func { __weak typeof(self) weakSelf = self; void (^block)(void) = ^{ NSLog(@"%d", weakSelf.value); }; block(); } @end
3.2.3 变量捕获和修改规则
- ArkTS 箭头函数:箭头函数本身不涉及特殊的变量捕获,它对外部变量的访问遵循其所在作用域的规则。
- ArkTS 闭包:自动捕获外部函数作用域的变量,可直接修改捕获的变量。
- C++ Lambda:通过捕获列表精确控制对外部变量的捕获方式,值捕获时不能修改捕获的变量,引用捕获可以修改。
- Swift 闭包:可通过捕获列表指定对外部变量的捕获方式,默认情况下捕获的变量是常量,若要修改需在闭包内使用 var 重新声明。
- Objective - C Block:默认按值捕获外部变量,若要修改需使用 __block 修饰。
3.2.4 应用场景侧重点
- ArkTS 箭头函数:主要用于前端开发场景,简化代码,特别是在处理数组操作和保持 this 指向方面有优势。
- ArkTS 闭包:侧重于数据封装和状态管理,实现函数的私有变量和方法。
- C++ Lambda:常用于算法库、多线程编程、STL 容器操作等场景,方便实现各种自定义的操作逻辑。
- Swift 闭包:广泛应用于集合操作、异步编程、动画处理、委托模式替代等场景。
- Objective - C Block:常用于异步操作、回调函数、排序、视图动画等场景。
更多推荐



所有评论(0)