JavaScript 主机环境

QML 提供为编写 QML 应用程序量身定制的 JavaScript 主机环境。该环境不同于浏览器或 Node.js 等服务器端 JavaScript 环境提供的主机环境。例如,QML 不提供浏览器环境中常见的window 对象或DOM API

通用基础

与浏览器或服务器端 JavaScript 环境一样,QML Runtime 实现了ECMAScript 语言规范标准。这样就能访问标准定义的所有内置类型和函数,如对象、数组和数学。QML Runtime 实现了该标准的第 7 版。

QML Runtime 还实现了Nullish Coalescing(??) (自 Qt 5.15 起)和Optional Chaining(?.) (自 Qt 6.2 起)。

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

类型注释和断言

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

function doThings(a: int, b: string) : QtObject { ... }

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

这一规则的例外是分配给信号处理器的函数:在那里,禁止使用类型注解,以避免与信号类型不匹配。这不会给工具带来问题,因为信号已经提供了必要的信息。

还可以使用类型断言(有时称为as-casts)将对象转换为不同的对象类型。如果对象实际上属于给定的类型,那么类型断言会返回相同的对象。如果不是,则返回null 。在下面的代码段中,我们在访问parent 对象的一个特定成员之前,断言该对象是Rectangle

Item {
    property color parentColor: (parent as Rectangle)?.color || "red"
}

如果父对象实际上不是矩形,可选的连锁 (?.) 可以避免抛出异常。在这种情况下,"red "会被选为parentColor

自 Qt 6.7 以来,在调用函数时始终执行类型注解。必要时会将值强制为所需类型。以前,解释器和 JIT 编译器会忽略类型注解,但在编译为 C++ 时,qmlcachegenqmlsc会强制执行类型注解。这可能会在某些情况下导致行为上的差异。为了明确请求解释器和 JIT 的旧行为,您可以在 QML 文档中添加以下内容:

pragma FunctionSignatureBehavior: Ignored

QML 全局对象

QML JavaScript 主机环境实现了许多主机对象和函数,详见QML 全局对象(QML Global Object)文档。

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

JavaScript 对象和函数

QML 引擎支持的 JavaScript 对象、函数和属性列表,可在JavaScript 对象和函数列表(List of JavaScript Objects and Functions)中找到。

请注意,QML 对本地对象做了以下修改:

  • String 原型添加了arg() 函数。
  • DateNumber 原型中添加了本地感知转换函数。

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

var v = something();
if (!v instanceof Item) {
    throw new TypeError("I need an Item type!");
}

...

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 指的是 scope 对象。在所有其他情况下,this 的值在 QML 中是未定义的。

    要引用特定对象,请提供id

    Item {
        width: 200; height: 100
        function mouseAreaClicked(area) {
            console.log("Clicked in area at: " + area.x + ", " + area.y);
        }
        // This will pass area to the function
        MouseArea {
            id: area
            y: 50; height: 50; width: 200
            onClicked: mouseAreaClicked(area)
        }
    }

另请参阅 范围和命名解析

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.