JavaScript宿主环境#

QML引擎提供的JavaScript宿主环境的描述

QML提供了一个定制的JavaScript宿主环境,适用于编写QML应用程序。此环境与浏览器或Node.js等服务器端JavaScript环境提供的宿主环境不同。例如,QML不提供类似于在浏览器环境中常见的window对象或DOM API

通用基础#

与浏览器或服务器端JavaScript环境类似,QML运行时实现了ECMAScript语言规范标准。这提供了访问标准定义的所有内置类型和函数,例如Object、Array和Math。QML运行时实现了该标准的第7版。

空合并运算符 (??)(自Qt 5.15开始)和可选链接运算符 (?.)(自Qt 6.2开始)也已在QML运行时中实现。

标准的ECMAScript内置函数在QML文档中没有明确记录。有关它们的使用信息,请参阅ECMA-262第7版标准或许多在线JavaScript参考和教程网站之一,例如W3Schools JavaScript参考(JavaScript对象参考部分)。许多网站侧重于浏览器中的JavaScript,因此在某些情况下可能需要查阅规范以确定给定函数或对象是否是标准ECMAScript的一部分或特定于浏览器环境。在上面的W3Schools链接中,JavaScript Objects Reference部分通常涵盖标准,而Browser Objects ReferenceHTML DOM Objects Reference部分是特定于浏览器的(因此不适用于QML)。

类型注解和断言#

QML文档中的函数声明可以,也应该包含类型注解。类型注解附加到参数的声明和函数本身,用于注解返回类型。以下函数接受一个和一个参数,并返回一个

类型注解有助于工具如Qt Creator和qmllint理解代码并提供更好的诊断。此外,它们使函数更容易从C++中使用。有关更多信息,请参阅从C++与QML对象交互

类型断言(有时称为as-casts)也可以用来将对象转换为不同的对象类型。如果对象确实是给定类型,则类型断言返回相同的对象。如果不是,它返回null。在下面的代码片段中,我们断言parent对象是Rectangle类型,然后在访问它的特定成员之前进行断言。

可选的链接操作符(?.)可以在父对象实际上不是矩形时避免抛出异常。在这种情况下,“red”被选为parentColor

自从Qt 6.7以来,在调用函数时始终强制执行类型注解。根据需要将值强制转换为所需类型。以前,类型注解被解释器和JIT编译器忽略,但在将代码编译为C++时由qmlcachegenqmlsc强制执行。这可能会在某些边缘情况下导致行为差异。为了显式请求解释器和JIT的老行为,可以将以下内容添加到您的QML文档中

QML全局对象

QML JavaScript宿主环境实现了一些宿主对象和函数,详细内容请见QML全局对象文档。

这些宿主对象和函数总是可用,无论是否导入了任何模块。

JavaScript对象和函数

支持的JavaScript对象、函数及其属性的列表可以在JavaScript对象和函数列表中找到。

请注意,QML对原生对象做了以下修改

  • String原型添加了arg()函数。

  • DateNumber原型添加了区域设置感知的转换函数。

此外,QML还扩展了instanceof函数的行为,以允许对QML类型进行类型检查。这意味着您可以用来验证变量确实是期望的类型,例如

JavaScript环境限制

QML对JavaScript代码实施以下限制

  • 位于.qml文件中的JavaScript代码不能修改全局对象。位于.js文件的JavaScript代码可以修改全局对象,并且这些修改在导入.qml文件时将是可见的。

    在QML中,全局对象是常量——现有的属性不能被修改或删除,而且不能创建新属性。

    大多数JavaScript程序不故意修改全局对象。然而,JavaScript自动创建未声明的变量是一种隐式修改全局对象的方式,这在QML中是被禁止的。

    假设在作用域链中没有变量a存在,以下代码在QML中是非法的

    // Illegal modification of undeclared variable
    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对象的全局代码将无法正确执行。

    // Invalid global code - the "rootObject" variable is undefined
    var initialPosition = { rootObject.x, rootObject.y }
    

    存在此限制,因为QML环境尚未完全建立。要在环境设置完成后运行代码,请参阅应用程序启动代码中的JavaScript

  • 在QML的大部分上下文中,此值(`this`)是未定义的。

    在从JavaScript绑定属性时,支持`this`关键字。在QML绑定表达式、QML信号处理器和QML声明的函数中,`this`指代作用域对象。在所有其他情况下,在QML中,`this`的值是未定义的。

    要引用特定对象,请提供一个id。例如