JavaScript 宿主环境¶
QML引擎提供的JavaScript宿主环境描述
QML 提供了一个专门用于编写 QML 应用程序的 JavaScript 宿主环境。这个环境与浏览器或服务器端 JavaScript 环境(如 Node.js)提供的宿主环境不同。例如,QML 不提供浏览器环境中常见的 window
对象或 DOM API
。
通用基础¶
与浏览器或服务器端JavaScript环境类似,QML运行时实现了ECMAScript语言规范标准。这提供了对标准定义的所有内置类型和函数的访问,例如Object、Array和Math。QML运行时实现了该标准的第7版。
Nullish Coalescing (??
) (自 Qt 5.15 起) 和 Optional Chaining (?.
) (自 Qt 6.2 起) 也在 QML 运行时中实现。
QML文档中没有明确记录标准的ECMAScript内置函数。有关它们使用的更多信息,请参考ECMA-262第7版标准或许多在线JavaScript参考和教程网站之一,例如W3Schools JavaScript参考(JavaScript对象参考部分)。许多网站专注于浏览器中的JavaScript,因此在某些情况下,您可能需要仔细检查规范以确定给定函数或对象是标准ECMAScript的一部分还是特定于浏览器环境。在上述W3Schools链接的情况下,JavaScript Objects Reference
部分通常涵盖标准,而Browser Objects Reference
和HTML DOM Objects Reference
部分是特定于浏览器的(因此不适用于QML)。
类型注解和断言¶
在QML文档中的函数声明可以并且应该包含类型注释。类型注释附加在参数的声明和函数本身上,用于注释返回类型。以下函数接受一个int
和一个string
参数,并返回一个QtObject
:
类型注释帮助像Qt Creator和qmllint这样的工具理解代码并提供更好的诊断。此外,它们使得从C++中使用函数更加容易。更多信息请参见从C++与QML对象交互。
类型断言(有时称为as-casts)也可以用于将对象转换为不同的对象类型。如果对象实际上是给定类型,则类型断言返回相同的对象。如果不是,则返回null
。在以下代码片段中,我们在访问特定成员之前断言parent
对象是Rectangle
。
可选链(?.
)可以避免在父元素实际上不是一个矩形时抛出异常。在这种情况下,选择“red”作为parentColor
。
自 Qt 6.7 起,调用函数时始终强制执行类型注释。值会根据需要强制转换为所需的类型。以前,类型注释被解释器和 JIT 编译器忽略,但在编译为 C++ 时由 qmlcachegen 和 qmlsc 强制执行。这可能导致在某些边缘情况下行为上的差异。为了明确请求解释器和 JIT 的旧行为,您可以在 QML 文档中添加以下内容:
QML 全局对象¶
QML JavaScript 宿主环境实现了许多宿主对象和函数,详细信息请参阅 QML 全局对象 文档。
这些主机对象和函数始终可用,无论是否导入了任何模块。
JavaScript 对象和函数¶
QML引擎支持的JavaScript对象、函数和属性的列表可以在JavaScript对象和函数列表中找到。
请注意,QML对原生对象进行了以下修改:
此外,QML还扩展了instanceof函数的行为,以允许对QML类型进行类型检查。这意味着你可以使用它来验证一个变量确实是你期望的类型,例如:
JavaScript 环境限制¶
QML 对 JavaScript 代码实现了以下限制:
写在
.qml
文件中的JavaScript代码不能修改全局对象。而写在.js文件中的JavaScript代码可以修改全局对象,并且这些修改在imported后对.qml文件可见。在QML中,全局对象是常量——现有的属性不能被修改或删除,也不能创建新的属性。
大多数JavaScript程序不会有意修改全局对象。然而,JavaScript自动创建未声明的变量是对全局对象的隐式修改,这在QML中是被禁止的。
假设
a
变量在作用域链中不存在,以下代码在QML中是非法的:// 非法修改未声明的变量 a = 1; for (var ii = 1; ii < 10; ++ii) a = a * ii; console.log("Result: " + a);可以简单地将其修改为以下合法代码。
var a = 1; for (var ii = 1; ii < 10; ++ii) a = a * ii; console.log("Result: " + a);任何试图修改全局对象的尝试——无论是隐式还是显式——都会导致异常。如果未捕获,这将导致打印警告,其中包含违规代码的文件和行号。
全局代码在缩减的作用域中运行。
在启动期间,如果QML文件包含带有“全局”代码的外部JavaScript文件,它将在仅包含外部文件本身和全局对象的作用域中执行。也就是说,它将无法访问它通常可以访问的QML对象和属性。
允许仅访问脚本局部变量的全局代码。这是一个有效的全局代码示例。
var colors = [ "red", "blue", "green", "orange", "purple" ];访问QML对象的全局代码将无法正确运行。
// 无效的全局代码 - "rootObject"变量未定义 var initialPosition = { rootObject.x, rootObject.y }此限制存在是因为QML环境尚未完全建立。要在环境设置完成后运行代码,请参阅应用程序启动代码中的JavaScript。
在大多数上下文中,
this
的值在 QML 中是未定义的。当从 JavaScript 绑定属性时,支持
this
关键字。在 QML 绑定表达式、QML 信号处理程序和 QML 声明的函数中,this
指的是作用域对象。在所有其他情况下,this
的值在 QML 中是未定义的。要引用特定对象,请提供
id
。例如:另请参阅