MST

星途 面试题库

面试题:TypeScript装饰器的组合使用及顺序问题

假设你有三个装饰器@decorator1、@decorator2、@decorator3,应用在一个类的方法上。请说明装饰器组合使用时的顺序是如何影响最终结果的,并通过代码示例展示不同顺序下方法行为的变化。同时解释为什么会出现这样的结果。
15.2万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试
  1. 装饰器顺序影响结果的原理
    • 装饰器本质上是函数,当多个装饰器应用于一个函数(或类的方法)时,它们的顺序是从内到外执行的。也就是说,离被装饰函数最近的装饰器最先执行,然后依次向外。
    • 每个装饰器都会对原函数进行一定的修改或增强,后续的装饰器是基于前一个装饰器修改后的函数进行操作的,所以装饰器的顺序不同,最终对原函数的修改结果也会不同。
  2. 代码示例
def decorator1(func):
    def wrapper(*args, **kwargs):
        print("Decorator 1 before")
        result = func(*args, **kwargs)
        print("Decorator 1 after")
        return result
    return wrapper


def decorator2(func):
    def wrapper(*args, **kwargs):
        print("Decorator 2 before")
        result = func(*args, **kwargs)
        print("Decorator 2 after")
        return result
    return wrapper


def decorator3(func):
    def wrapper(*args, **kwargs):
        print("Decorator 3 before")
        result = func(*args, **kwargs)
        print("Decorator 3 after")
        return result
    return wrapper


class MyClass:
    @decorator1
    @decorator2
    @decorator3
    def my_method(self):
        print("Inside my_method")


my_obj = MyClass()
my_obj.my_method()
  • 输出结果
Decorator 1 before
Decorator 2 before
Decorator 3 before
Inside my_method
Decorator 3 after
Decorator 2 after
Decorator 1 after
  • 解释:在这个例子中,@decorator3my_method最近,所以它最先对my_method进行装饰。当调用my_obj.my_method()时,实际上调用的是decorator1装饰后的函数,而decorator1装饰后的函数又包含了decorator2装饰后的函数,decorator2装饰后的函数又包含了decorator3装饰后的函数。所以先打印出Decorator 1 before,然后进入decorator2wrapper打印Decorator 2 before,再进入decorator3wrapper打印Decorator 3 before,接着执行原my_method打印Inside my_method,之后从decorator3wrapper开始返回,依次打印Decorator 3 afterDecorator 2 afterDecorator 1 after

  • 如果改变装饰器顺序

class MyClass2:
    @decorator3
    @decorator2
    @decorator1
    def my_method(self):
        print("Inside my_method")


my_obj2 = MyClass2()
my_obj2.my_method()
  • 输出结果
Decorator 3 before
Decorator 2 before
Decorator 1 before
Inside my_method
Decorator 1 after
Decorator 2 after
Decorator 3 after
  • 解释:此时@decorator1my_method最近,所以它最先对my_method进行装饰。调用my_obj2.my_method()时,执行顺序和之前不同,先打印Decorator 3 before,再进入decorator2wrapper打印Decorator 2 before,接着进入decorator1wrapper打印Decorator 1 before,执行原my_method打印Inside my_method,然后从decorator1wrapper开始返回,依次打印Decorator 1 afterDecorator 2 afterDecorator 3 after

综上所述,装饰器的顺序不同,对原函数(或类的方法)的增强和修改顺序也不同,导致最终的行为和输出结果不同。