一、箭头函数(又名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:常用于异步操作、回调函数、排序、视图动画等场景。
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐