JS装饰器内无法访问函数name属性及执行顺序倒置问题咨询
问题成因与解决方案
1. 无法访问fn.name的问题
成因
每个装饰器返回的都是匿名箭头函数,这类函数的name属性默认为空字符串。你对rectangleArea的装饰顺序是先包裹countParams,再包裹requireIntegers:
- 第一次赋值后,
rectangleArea指向countParams返回的匿名函数,name为空 - 第二次赋值时,传入
requireIntegers的fn就是这个匿名函数,自然读取不到有效的name值
规避方案
在装饰器返回新函数时,手动保留原函数的name属性,可通过Object.defineProperty实现,修改后的装饰器示例:
const countParams = (fn) => { const wrapper = (...params) => { console.log('countParams', fn.name) if (params.length !== fn.length) { throw new Error(`Incorrect number of parameters for ${fn.name}!`); } return fn(...params); } // 手动保留原函数name Object.defineProperty(wrapper, 'name', { value: fn.name }); return wrapper; }
也可以直接用普通函数代替匿名箭头函数,在定义时明确指定函数名。
2. 装饰器自下向上执行的问题
成因
装饰器的本质是函数嵌套包装,你的连续赋值操作等价于rectangleArea = requireIntegers(countParams(rectangleArea))。调用函数时会从最外层的包装逻辑开始执行,逐层向内深入,后绑定的装饰逻辑会先触发,看起来就是自下向上执行。
规避方案
调整装饰器的绑定顺序即可:希望先执行的装饰逻辑放在后面绑定,希望后执行的装饰逻辑放在前面绑定。比如你想要先校验参数数量再校验参数类型,就把requireIntegers的绑定放在countParams前面:
rectangleArea = requireIntegers(rectangleArea); rectangleArea = countParams(rectangleArea);
内容的提问来源于stack exchange,提问作者RoyBlunk
相关产品推荐
相关产品推荐

