En esta página

Ámbito y resolución de nombres

Los enlaces de propiedades QML, las funciones en línea y los archivos JavaScript importados se ejecutan en un ámbito JavaScript. El ámbito controla a qué variables puede acceder una expresión y qué variable tiene prioridad cuando dos o más nombres entran en conflicto.

Dado que el mecanismo de ámbito integrado de JavaScript es muy sencillo, QML lo mejora para que se adapte de forma más natural a las extensiones del lenguaje QML.

Ámbito de JavaScript

Las extensiones de ámbito de QML no interfieren con el ámbito natural de JavaScript. Los programadores de JavaScript pueden reutilizar sus conocimientos existentes al programar funciones, enlaces de propiedades o archivos JavaScript importados en QML.

En el siguiente ejemplo, el método addConstant() añadirá 13 al parámetro pasado tal y como esperaría el programador, independientemente del valor de las propiedades a y b del objeto QML.

QtObject {
    property int a: 3
    property int b: 9

    function addConstant(b) {
        var a = 13;
        return b + a;
    }
}

El hecho de que QML respete las reglas de alcance normales de JavaScript se aplica incluso en los enlaces. Esta abominación totalmente maligna asignará 12 a la propiedad a del objeto QML.

QtObject {
    property int a

    a: { var a = 12; a; }
}

Cada expresión, función o archivo JavaScript en QML tiene su propio objeto variable único. Las variables locales declaradas en uno nunca entrarán en conflicto con las variables locales declaradas en otro.

Nombres de tipo y archivos JavaScript importados

Los documentos QML incluyen sentencias import que definen los nombres de tipo y los archivos JavaScript visibles para el documento. Además de su uso en la propia declaración QML, los nombres de tipo son utilizados por el código JavaScript cuando accede a propiedades adjuntas y valores de enumeración.

El efecto de una importación se aplica a todos los enlaces de propiedades y funciones JavaScript del documento QML, incluso a los que se encuentran en componentes anidados en línea. El siguiente ejemplo muestra un archivo QML sencillo que accede a algunos valores de enumeración y llama a una función JavaScript importada.

import QtQuick 2.0
import "code.js" as Code

ListView {
    snapMode: ListView.SnapToItem

    delegate: Component {
        Text {
            elide: Text.ElideMiddle
            text: "A really, really long string that will require eliding."
            color: Code.defaultColor()
        }
    }
}

Objeto de ámbito vinculante

Un objeto que tiene una propiedad vinculante se conoce como objeto de ámbito de la vinculación. En el siguiente ejemplo, el objeto Item es el objeto de ámbito del enlace.

Item {
    anchors.left: parent.left
}

Los enlaces tienen acceso a las propiedades del objeto de ámbito sin restricciones. En el ejemplo anterior, el enlace accede directamente a la propiedad parent de Item, sin necesidad de ningún tipo de prefijo de objeto. QML introduce un enfoque más estructurado y orientado a objetos de JavaScript y, en consecuencia, no requiere el uso de la propiedad this de JavaScript.

Hay que tener cuidado al acceder a propiedades adjuntas desde bindings debido a su interacción con el objeto scope. Conceptualmente, las propiedades adjuntas existen en todos los objetos, aunque sólo tengan efecto en un subconjunto de ellos. En consecuencia, las lecturas de propiedades adjuntas no cualificadas siempre se resolverán a una propiedad adjunta en el objeto de ámbito, que no siempre es lo que el programador pretendía.

Por ejemplo, el tipo PathView adjunta propiedades de valor interpolado a sus delegados dependiendo de su posición en la ruta. Dado que PathView sólo adjunta de forma significativa estas propiedades al objeto raíz del delegado, cualquier subobjeto que acceda a ellas debe calificar explícitamente al objeto raíz, como se muestra a continuación.

PathView {
    delegate: Component {
        Rectangle {
            id: root
            Image {
                scale: root.PathView.scale
            }
        }
    }
}

Si el objeto Image omitiera el prefijo root, accedería inadvertidamente a la propiedad PathView.scale adjunta a sí mismo.

Ámbito de los componentes

Cada componente QML de un documento QML define un ámbito lógico. Cada documento tiene al menos un componente raíz, pero también puede tener otros subcomponentes en línea. El ámbito del componente es la unión de los identificadores de objeto dentro del componente y las propiedades del objeto raíz del componente.

Item {
    property string title

    Text {
        id: titletype
        text: "<b>" + title + "</b>"
        font.pixelSize: 22
        anchors.top: parent.top
    }

    Text {
        text: titletype.text
        font.pixelSize: 18
        anchors.bottom: parent.bottom
    }
}

El ejemplo anterior muestra un componente QML sencillo que muestra una cadena de título de texto enriquecido en la parte superior y una copia más pequeña del mismo texto en la parte inferior. El primer tipo Text accede directamente a la propiedad title del componente cuando forma el texto a mostrar. El hecho de que se pueda acceder directamente a las propiedades del tipo raíz hace que sea trivial distribuir los datos por todo el componente.

El segundo tipo Text utiliza un id para acceder directamente al texto del primero. Los ID son especificados explícitamente por el programador de QML, por lo que siempre tienen prioridad sobre otros nombres de propiedades (excepto los del ámbito JavaScript). Por ejemplo, en el improbable caso de que el objeto scope del binding tuviera una propiedad titletype en el ejemplo anterior, el id titletype seguiría teniendo preferencia.

Jerarquía de instancias de componentes

En QML, las instancias de componentes conectan sus ámbitos de componentes para formar una jerarquía de ámbitos. Las instancias de componentes pueden acceder directamente a los ámbitos de componentes de sus antepasados.

La forma más sencilla de demostrarlo es con subcomponentes en línea cuyos ámbitos de componente se definen implícitamente como hijos del componente externo.

Item {
    property color defaultColor: "blue"

    ListView {
        delegate: Component {
            Rectangle {
                color: defaultColor
            }
        }
    }
}

La jerarquía de instancias de componentes permite a las instancias del componente delegado acceder a la propiedad defaultColor del tipo Item. Por supuesto, si el componente delegado hubiera tenido una propiedad llamada defaultColor, ésta habría tenido prioridad.

La jerarquía del ámbito de instancia del componente también se extiende a los componentes fuera de línea. En el siguiente ejemplo, el componente TitlePage.qml crea dos instancias TitleText. Aunque el tipo TitleText se encuentra en un archivo independiente, sigue teniendo acceso a la propiedad title cuando se utiliza desde TitlePage. QML es un lenguaje de ámbito dinámico: dependiendo de dónde se utilice, la propiedad title puede resolverse de forma diferente.

// TitlePage.qml
import QtQuick 2.0
Item {
    property string title

    TitleText {
        size: 22
        anchors.top: parent.top
    }

    TitleText {
        size: 18
        anchors.bottom: parent.bottom
    }
}

// TitleText.qml
import QtQuick 2.0
Text {
    property int size
    text: "<b>" + title + "</b>"
    font.pixelSize: size
}

El ámbito dinámico es muy potente, pero debe utilizarse con precaución para evitar que el comportamiento del código QML sea difícil de predecir. En general, sólo debe utilizarse en los casos en que los dos componentes ya estén estrechamente acoplados de otra forma. Al construir componentes reutilizables, es preferible utilizar interfaces de propiedades, como ésta:

// TitlePage.qml
import QtQuick 2.0
Item {
    id: root
    property string title

    TitleText {
        title: root.title
        size: 22
        anchors.top: parent.top
    }

    TitleText {
        title: root.title
        size: 18
        anchors.bottom: parent.bottom
    }
}

// TitleText.qml
import QtQuick 2.0
Text {
    property string title
    property int size

    text: "<b>" + title + "</b>"
    font.pixelSize: size
}

No haga referencia al objeto raíz id desde otros componentes QML

Evite acceder a id de un objeto raíz desde fuera del archivo QML en el que está definido. Los valores de id sólo son válidos dentro del mismo documento, y confiar en ellos desde otros componentes rompe la encapsulación y los límites de los componentes.

// Main.qml
import QtQuick

Item {
    id: root
    CustomItem { }
}

// CustomItem.qml
import QtQuick

Rectangle {
    width: root.width
    height: root.height / 2
    color: "red"
}

En el ejemplo anterior, root no está declarado en CustomItem.qml. El código sigue funcionando porque CustomItem se instancia en un contexto en el que existe root, lo que está permitido por las reglas de ámbito dinámico de QML. Sin embargo, esto crea una dependencia implícita del ámbito externo, lo que hace que el componente sea poco fiable y más difícil de reutilizar cuando se carga dinámicamente o se utiliza en un contexto diferente. Este patrón también puede dar lugar a errores sutiles. Por ejemplo, si otro objeto de la cadena de ámbito utiliza el mismo id, puede hacer sombra al esperado, dando lugar a un comportamiento inesperado.

Para que los componentes sean fiables y reutilizables, accede al estado externo sólo a través de propiedades explícitas, alias de propiedades o señales. Evite depender de valores de ámbito externo id.

El siguiente ejemplo sustituye el ámbito dinámico por una API de componentes explícita.

// Main.qml
import QtQuick
import QtQuick.Window

Window {
    id: root
    width: 400
    height: 300
    visible: true

    CustomItem {
        width: root.width
        height: root.height
        boxColor: "blue"
    }
}

// CustomItem.qml
import QtQuick

Item {
    id: container
    property alias boxColor: rect.color

    Rectangle {
        id: rect
        width: container.width
        height: container.height / 2
        color: "red"
    }
}

Aplique la misma regla a todos los objetos internos declarados con id dentro de un componente.

// MyItem.qml
import QtQuick

Item {
    Item {
        id: internalCounter
        property int count: 5
    }
}

// main.qml
import QtQuick

MyItem {
    Component.onCompleted: {
        console.log(internalCounter.count);
    }
}

En el ejemplo anterior, el acceso a id internalCounter desde otro archivo QML provoca un ReferenceError porque id es un documento local y no se puede acceder a él fuera del archivo QML en el que está declarado.

Si un objeto interno necesita exponer su estado o comportamiento, exponlo explícitamente a través de propiedades, alias de propiedades o señales.

El siguiente ejemplo expone el estado interno a través de una API de componente explícita en lugar de confiar en el acceso directo a un documento local id.

// MyItem.qml
import QtQuick

Item {
    Item {
        id: internalCounter
        property int count: 5
    }
    property alias internalCount: internalCounter.count
}

// main.qml
import QtQuick

MyItem {
    Component.onCompleted: {
        console.log(internalCount);
    }
}

Esto ayuda a mantener claros los límites de los componentes y mejora la escalabilidad y la comprobabilidad.

Propiedades sobrescritas

QML permite que los nombres de propiedades definidos en una declaración de objeto sean sustituidos por propiedades declaradas en otra declaración de objeto que extienda la primera. Por ejemplo:

// Displayable.qml
import QtQuick 2.0
Item {
    property string title
    property string detail

    Text {
        text: "<b>" + title + "</b><br>" + detail
    }

    function getTitle() { return title }
    function setTitle(newTitle) { title = newTitle }
}

// Person.qml
import QtQuick 2.0
Displayable {
    property string title
    property string firstName
    property string lastName

    function fullName()  { return title + " " + firstName + " " + lastName }
}

Aquí, el nombre title se da tanto al encabezado del texto de salida para Displayable, como al título honorífico del objeto Person.

Una propiedad anulada se resuelve según el ámbito en el que se hace referencia a ella. Dentro del ámbito del componente Persona, o desde un ámbito externo que haga referencia a una instancia del componente Persona, title resuelve a la propiedad declarada dentro de Person.qml. La función fullName hará referencia a la propiedad title declarada dentro de Person.

Sin embargo, dentro del componente Displayable, title hace referencia a la propiedad declarada en Displayable.qml. Las funciones getTitle() y setTitle(), y el enlace para la propiedad text del objeto Text harán referencia a la propiedad title declarada en el componente Displayable.

A pesar de compartir el mismo nombre, las dos propiedades son completamente independientes. Un controlador de señal onChanged para una de las propiedades no se activará por un cambio en la otra propiedad con el mismo nombre. Un alias de cualquiera de las propiedades hará referencia a una u otra, pero no a ambas.

Objeto global JavaScript

QML prohíbe los nombres de tipo, id y propiedad que entren en conflicto con las propiedades del objeto global para evitar cualquier confusión. Los programadores pueden estar seguros de que Math.min(10, 9) funcionará siempre como se espera.

Consulte Entorno de host JavaScript para obtener más información.

© 2026 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.