QML JS类构造函数中箭头函数if块内this变为undefined问题
该异常为Qt QML内置JavaScript引擎(QJSEngine)的已知实现缺陷,完全不符合ECMAScript标准语法规则,具体成因如下:
- Qt 5.15.x、Qt 6.0~6.3版本的QJSEngine在处理嵌套箭头函数的块级作用域时,作用域链遍历逻辑存在漏洞:当箭头函数内部出现
if/for/switch等带独立块级作用域的语法结构时,引擎会错误跳过箭头函数捕获的外层this上下文,在当前块作用域内找不到绑定的this值时就直接返回undefined,块外代码因为没有触发块级作用域的上下文切换逻辑,所以this取值符合预期。 - 该问题已经在Qt 6.4及以上版本的QJSEngine中修复,升级Qt版本即可从根本上解决该异常。
低版本Qt临时规避方案
可以通过以下两种方式在不升级Qt版本的前提下规避该问题:
- 在箭头函数入口先将外层this缓存到局部变量,后续在块内直接访问该局部变量即可:
import QtQuick 2.14 Item { Component.onCompleted: { class Bugtest { constructor() { this.foo = 123; const that = this; // 提前缓存this ((arg) => { print("BEFORE if: this="+that+", foo="+that.foo); if (true) { print("DURING if: this="+that); // 不会返回undefined } print("AFTER if: this="+that+", foo="+that.foo); })(42); print("At constructor exit: this="+this+", foo="+this.foo); } }; var xyz = new Bugtest(); } }
- 将匿名箭头函数替换为普通函数,主动绑定外层this:
(function(arg) { print("BEFORE if: this="+this+", foo="+this.foo); if (true) { print("DURING if: this="+this); } print("AFTER if: this="+this+", foo="+this.foo); }.bind(this))(42);
内容的提问来源于stack exchange,提问作者jimav
相关产品推荐
相关产品推荐

