Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
scope.qdoc
Go to the documentation of this file.
1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
3/*!
4\page qtqml-documents-scope.html
5\title Scope and Naming Resolution
6\brief overview of scope and naming resolution
7
8QML property bindings, inline functions, and imported JavaScript files all
9run in a JavaScript scope. Scope controls which variables an expression can
10access, and which variable takes precedence when two or more names conflict.
11
12As JavaScript's built-in scope mechanism is very simple, QML enhances it to fit
13more naturally with the QML language extensions.
14
15\section1 JavaScript Scope
16
17QML's scope extensions do not interfere with JavaScript's natural scoping.
18JavaScript programmers can reuse their existing knowledge when programming
19functions, property bindings or imported JavaScript files in QML.
20
21In the following example, the \c {addConstant()} method will add 13 to the
22parameter passed just as the programmer would expect irrespective of the
23value of the QML object's \c a and \c b properties.
24
25\code
26QtObject {
27 property int a: 3
28 property int b: 9
29
30 function addConstant(b) {
31 var a = 13;
32 return b + a;
33 }
34}
35\endcode
36
37That QML respects JavaScript's normal scoping rules even applies in bindings.
38This totally evil, abomination of a binding will assign 12 to the QML object's
39\c a property.
40
41\code
42QtObject {
43 property int a
44
45 a: { var a = 12; a; }
46}
47\endcode
48
49Every JavaScript expression, function or file in QML has its own unique
50variable object. Local variables declared in one will never conflict
51with local variables declared in another.
52
53\section1 Type Names and Imported JavaScript Files
54
55\l {QML Documents} include import statements that define the type names
56and JavaScript files visible to the document. In addition to their use in the
57QML declaration itself, type names are used by JavaScript code when accessing
58\l {Attached Properties and Attached Signal Handlers}{attached properties} and enumeration values.
59
60The effect of an import applies to every property binding, and JavaScript
61function in the QML document, even those in nested inline components. The
62following example shows a simple QML file that accesses some enumeration
63values and calls an imported JavaScript function.
64
65\code
66import QtQuick 2.0
67import "code.js" as Code
68
69ListView {
70 snapMode: ListView.SnapToItem
71
72 delegate: Component {
73 Text {
74 elide: Text.ElideMiddle
75 text: "A really, really long string that will require eliding."
76 color: Code.defaultColor()
77 }
78 }
79}
80\endcode
81
82\section1 Binding Scope Object
83
84An object which has a \l{Property Binding}{property binding} is known as the
85binding's \e{scope object}. In the following example, the \l Item object is
86the binding's scope object.
87
88\code
89Item {
90 anchors.left: parent.left
91}
92\endcode
93
94Bindings have access to the scope object's properties without qualification.
95In the previous example, the binding accesses the \l Item's \c parent property
96directly, without needing any form of object prefix. QML introduces a more
97structured, object-oriented approach to JavaScript, and consequently does not
98require the use of the JavaScript \c this property.
99
100Care must be used when accessing \l {Attached Properties and Attached Signal Handlers}
101{attached properties} from bindings due
102to their interaction with the scope object. Conceptually attached properties
103exist on \e all objects, even if they only have an effect on a subset of those.
104Consequently unqualified attached property reads will always resolve to an
105attached property on the scope object, which is not always what the programmer
106intended.
107
108For example, the \l PathView type attaches interpolated value properties to
109its delegates depending on their position in the path. As PathView only
110meaningfully attaches these properties to the root object in the delegate, any
111sub-object that accesses them must explicitly qualify the root object, as shown
112below.
113
114\code
115PathView {
116 delegate: Component {
117 Rectangle {
118 id: root
119 Image {
120 scale: root.PathView.scale
121 }
122 }
123 }
124}
125\endcode
126
127If the \l Image object omitted the \c root prefix, it would inadvertently access
128the unset \c {PathView.scale} attached property on itself.
129
130\section1 Component Scope
131
132Each QML component in a QML document defines a logical scope. Each document
133has at least one root component, but can also have other inline sub-components.
134The component scope is the union of the object ids within the component and the
135component's root object's properties.
136
137\code
138Item {
139 property string title
140
141 Text {
142 id: titletype
143 text: "<b>" + title + "</b>"
144 font.pixelSize: 22
145 anchors.top: parent.top
146 }
147
148 Text {
149 text: titletype.text
150 font.pixelSize: 18
151 anchors.bottom: parent.bottom
152 }
153}
154\endcode
155
156The example above shows a simple QML component that displays a rich text title
157string at the top, and a smaller copy of the same text at the bottom. The first
158\c Text type directly accesses the component's \c title property when
159forming the text to display. That the root type's properties are directly
160accessible makes it trivial to distribute data throughout the component.
161
162The second \c Text type uses an id to access the first's text directly. IDs
163are specified explicitly by the QML programmer so they always take precedence
164over other property names (except for those in the \l {JavaScript Scope}). For
165example, in the unlikely event that the binding's \l {Binding Scope Object}{scope
166object} had a \c titletype property in the previous example, the \c titletype
167id would still take precedence.
168
169\section1 Component Instance Hierarchy
170
171In QML, component instances connect their component scopes together to form a
172scope hierarchy. Component instances can directly access the component scopes of
173their ancestors.
174
175The easiest way to demonstrate this is with inline sub-components whose component
176scopes are implicitly scoped as children of the outer component.
177
178\code
179Item {
180 property color defaultColor: "blue"
181
182 ListView {
183 delegate: Component {
184 Rectangle {
185 color: defaultColor
186 }
187 }
188 }
189}
190\endcode
191
192The component instance hierarchy allows instances of the delegate component
193to access the \c defaultColor property of the \c Item type. Of course,
194had the delegate component had a property called \c defaultColor that would
195have taken precedence.
196
197The component instance scope hierarchy extends to out-of-line components, too.
198In the following example, the \c TitlePage.qml component creates two
199\c TitleText instances. Even though the \c TitleText type is in a separate
200file, it still has access to the \c title property when it is used from within
201the \c TitlePage. QML is a dynamically scoped language - depending on where it
202is used, the \c title property may resolve differently.
203
204\code
205// TitlePage.qml
206import QtQuick 2.0
207Item {
208 property string title
209
210 TitleText {
211 size: 22
212 anchors.top: parent.top
213 }
214
215 TitleText {
216 size: 18
217 anchors.bottom: parent.bottom
218 }
219}
220
221// TitleText.qml
222import QtQuick 2.0
223Text {
224 property int size
225 text: "<b>" + title + "</b>"
226 font.pixelSize: size
227}
228\endcode
229
230Dynamic scoping is very powerful, but it must be used cautiously to prevent
231the behavior of QML code from becoming difficult to predict. In general it
232should only be used in cases where the two components are already tightly
233coupled in another way. When building reusable components, it is preferable
234to use property interfaces, like this:
235
236\code
237// TitlePage.qml
238import QtQuick 2.0
239Item {
240 id: root
241 property string title
242
243 TitleText {
244 title: root.title
245 size: 22
246 anchors.top: parent.top
247 }
248
249 TitleText {
250 title: root.title
251 size: 18
252 anchors.bottom: parent.bottom
253 }
254}
255
256// TitleText.qml
257import QtQuick 2.0
258Text {
259 property string title
260 property int size
261
262 text: "<b>" + title + "</b>"
263 font.pixelSize: size
264}
265\endcode
266
267\section1 Overridden Properties
268
269QML permits property names defined in an object declaration to be overridden by properties
270declared within another object declaration that extends the first. For example:
271
272\code
273// Displayable.qml
274import QtQuick 2.0
275Item {
276 property string title
277 property string detail
278
279 Text {
280 text: "<b>" + title + "</b><br>" + detail
281 }
282
283 function getTitle() { return title }
284 function setTitle(newTitle) { title = newTitle }
285}
286
287// Person.qml
288import QtQuick 2.0
289Displayable {
290 property string title
291 property string firstName
292 property string lastName
293
294 function fullName() { return title + " " + firstName + " " + lastName }
295}
296\endcode
297
298Here, the name \c title is given to both the heading of the output text for Displayable,
299and also to the honorific title of the Person object.
300
301An overridden property is resolved according to the scope in which it is referenced.
302Inside the scope of the Person component, or from an external scope that refers
303to an instance of the Person component, \c title resolves to the property
304declared inside Person.qml. The \c fullName function will refer to the \c title
305property declared inside Person.
306
307Inside the Displayable component, however, \c title refers to the property
308declared in Displayable.qml. The getTitle() and setTitle() functions, and the
309binding for the \c text property of the Text object will all refer to the \c title
310property declared in the Displayable component.
311
312Despite sharing the same name, the two properties are entirely separate. An
313onChanged signal handler for one of the properties will not be triggered by
314a change to the other property with the same name. An alias to either property
315will refer to one or the other, but not both.
316
317\section1 JavaScript Global Object
318
319QML disallows type, id and property names that conflict with the properties
320on the global object to prevent any confusion. Programmers can be confident
321that \c Math.min(10, 9) will always work as expected!
322
323See \l {JavaScript Host Environment} for more information.
324
325*/