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