1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
|
---
title: getter
slug: Web/JavaScript/Reference/Functions/get
translation_of: Web/JavaScript/Reference/Functions/get
---
<div>{{jsSidebar("Functions")}}</div>
<div>A sintaxe de <strong>get </strong>associa uma propriedade de um objeto a uma função que será chamada quando tal propriedade é acessada.</div>
<h2 id="Sintaxe">Sintaxe</h2>
<pre class="syntaxbox notranslate">{get <em>prop</em>() { ... } }
{get <em>[expression]</em>() { ... } }</pre>
<h3 id="Parâmetros">Parâmetros</h3>
<dl>
<dt><code>prop</code></dt>
<dd>O nome da propriedade à qual a função dada será associada.</dd>
<dt>expression</dt>
<dd>A partir do ECMAScript 6, você pode também utilizar expressões para um nome computado de uma propriedade para associar à função dada.</dd>
</dl>
<h2 id="Descrição">Descrição</h2>
<p>Às vezes é desejável que se permita acesso a uma propriedade que retorna um valor computado dinamicamente, ou você pode querer refletir o status de uma variável interna sem requerer o uso de chamadas de método explícitas. Em Javascript, isso pode ser feito com o uso de um <em>getter</em>. Não é possível simultaneamente ter um getter associado a uma propriedade e a mesma possuir um valor, embora seja possível usar um getter e um setter em conjunto para criar algo como uma pseudo-propriedade.</p>
<p>Note o seguinte quando for trabalhar com a sintaxe <em>get</em>:</p>
<ul>
<li>Pode haver um identificador que seja um número ou uma string;</li>
<li>Deve haver exatamente zero parâmetros (veja <a class="external" href="http://whereswalden.com/2010/08/22/incompatible-es5-change-literal-getter-and-setter-functions-must-now-have-exactly-zero-or-one-arguments/" rel="external nofollow">Incompatible <abbr title="ECMAScript 5th edition">ES5</abbr> change: literal getter and setter functions must now have exactly zero or one arguments</a> para mais informações)</li>
<li>Não deve haver mais de um getter para a mesma propriedade nem uma propriedade comum como o mesmo nome do getter (<code>{ get x() { }, get x() { } }</code> and <code>{ x: ..., get x() { } }</code> são proibidos).</li>
</ul>
<p>Um getter pode ser removido usando o operador <code><a href="/pt-BR/docs/Web/JavaScript/Reference/Operators/delete" title="en/Core_JavaScript_1.5_Reference/Operators/Special_Operators/delete_Operator">delete</a>.</code></p>
<h2 id="Exemplos">Exemplos</h2>
<h3 id="Definindo_um_getter_em_novos_objetos_em_inicializadores_de_objetos">Definindo um getter em novos objetos em inicializadores de objetos</h3>
<p>O exemplo abaixo irá criar a pseudo-propriedade <code>latest</code> para o objeto <code>obj</code>, que irá retornar o último item do array em <code>log</code>.</p>
<pre class="brush: js notranslate">var log = ['test'];
var obj = {
get latest () {
if (log.length == 0) return undefined;
return log[log.length - 1]
}
}
console.log (obj.latest); // Retornará "test".
</pre>
<p>Note que a tentativa de atribuir um valor a <code>latest não irá alterá-la.</code></p>
<h3 id="Removendo_um_getter_usando_o_operador_delete">Removendo um getter usando o operador <code>delete</code></h3>
<p>Se você quer remover um getter, você pode apenas utilizar <code><a href="/pt-BR/docs/Web/JavaScript/Reference/Operators/delete">delete</a>.</code></p>
<pre class="brush: js notranslate">delete obj.latest;
</pre>
<h3 id="Definindo_um_getter_em_objetos_existentes_usando_defineProperty">Definindo um getter em objetos existentes usando <code>defineProperty</code></h3>
<p>Para adicionar um getter a um objeto existente a qualquer momento, use {{jsxref("Object.defineProperty()")}}.</p>
<pre class="brush: js notranslate">var o = { a:0 }
Object.defineProperty(o, "b", { get: function () { return this.a + 1; } });
console.log(o.b) // Executa o getter, que retornará a + 1 (which is 1)</pre>
<h3 id="Usando_uma_propriedade_com_nome_computado">Usando uma propriedade com nome computado</h3>
<div class="note">
<p><strong>Nota:</strong> Propriedades com nome computado são uma tecnologia experimenta, parte da proposta do ECMAScript 6 e não é amplamente suportada pelos navegadores ainda. O exemplo abaixo irá disparar um <code>SyntaxError em ambientes sem suporte.</code></p>
</div>
<pre class="brush: js notranslate">var expr = "foo";
var obj = {
get [expr]() { return "bar"; }
};
console.log(obj.foo); // "bar"</pre>
<h3 id="Smart_self-overwriting_lazy_getters">Smart / self-overwriting / lazy getters</h3>
<p>Getters lhe dão uma maneira de definir uma propriedade de um objeto, mas eles não calculam o valor da propriedade até que sejam acessados. Um getter adia o custo de cálculo do valor até que o valor seja necessário e, se nunca o for, você não precisa pagar esse custo.</p>
<p>Uma técnica de otimização adicional para atrasar o cálculo do valor de uma propriedade e cacheá-lo para acesso futuro são os <strong>smart ou <a href="https://en.wikipedia.org/wiki/Memoization">memoized</a> getters</strong>. O valor é calculado na primeira vez que o getter é invocado, sendo então cacheado para que acessos subsequentes retornem o valor em cache sem recalculá-lo. Isso é util nas seguintes situações:</p>
<ul>
<li>Se o cálculo da propriedade é caro (usa muita RAM ou CPU, cria um worker, retorna um arquivo remoto, etc).</li>
<li>Se o valor não é necessário agora. Ele será utilizado depois ou, em alguns casos, nem mesmo o será.</li>
<li>Se for utilizado, ele será acessado diversas vezes e não há necessidade de recalcular um valor que nunca será alterado, ou não deveria ser recalculado.</li>
</ul>
<p>Isso significa que você não deveria utilizar um lazy getter para uma propriedade cujo valor você espera mudar, porque o getter nunca irá recalcular o valor.</p>
<p>No exemplo a seguir, o objeto tem um getter como uma propriedade própria (own property). Ao tentar obter essa propriedade que foi removida, ela será readicionada, mas implicitamente como uma propriedade comum desta vez. Finalmente, o valor será retornado.</p>
<pre class="brush: js notranslate">get notifier() {
delete this.notifier;
return this.notifier = document.getElementById("bookmarked-notification-anchor");
},</pre>
<p>Para o Firefox, veja também o código do módulo XPCOMUtils.jsm, que define a função <a href="/pt-BR/docs/Mozilla/JavaScript_code_modules/XPCOMUtils.jsm#defineLazyGetter()">defineLazyGetter()</a>.</p>
<h2 id="Especificações">Especificações</h2>
<table class="standard-table">
<tbody>
<tr>
<th scope="col">Especificação</th>
<th scope="col">Status</th>
<th scope="col">Comentário</th>
</tr>
<tr>
<td>{{SpecName('ES5.1', '#sec-11.1.5', 'Object Initializer')}}</td>
<td>{{Spec2('ES5.1')}}</td>
<td>Definição inicial.</td>
</tr>
<tr>
<td>{{SpecName('ES6', '#sec-method-definitions', 'Method definitions')}}</td>
<td>{{Spec2('ES6')}}</td>
<td>Adicionado nomes de propriedades computadas.</td>
</tr>
<tr>
<td>{{SpecName('ESDraft', '#sec-method-definitions', 'Method definitions')}}</td>
<td>{{Spec2('ESDraft')}}</td>
<td></td>
</tr>
</tbody>
</table>
<h2 id="Browser_compatibility">Compatibilidade com navegadores</h2>
<p>{{CompatibilityTable}}</p>
<div id="compat-desktop">
<table class="compat-table">
<tbody>
<tr>
<th>Feature</th>
<th>Chrome</th>
<th>Firefox (Gecko)</th>
<th>Internet Explorer</th>
<th>Opera</th>
<th>Safari</th>
</tr>
<tr>
<td>Suporte básico</td>
<td>{{CompatChrome(1)}}</td>
<td>{{ CompatGeckoDesktop("1.8.1") }}</td>
<td>{{ CompatIE(9) }}</td>
<td>9.5</td>
<td>3</td>
</tr>
<tr>
<td>Propriedades com nome computado</td>
<td>{{CompatNo}}</td>
<td>{{ CompatGeckoDesktop("34") }}</td>
<td>{{CompatNo}}</td>
<td>{{CompatNo}}</td>
<td>{{CompatNo}}</td>
</tr>
</tbody>
</table>
</div>
<div id="compat-mobile">
<table class="compat-table">
<tbody>
<tr>
<th>Feature</th>
<th>Android</th>
<th>Chrome for Android</th>
<th>Firefox Mobile (Gecko)</th>
<th>IE Mobile</th>
<th>Opera Mobile</th>
<th>Safari Mobile</th>
</tr>
<tr>
<td>Suporte básico</td>
<td>{{CompatVersionUnknown}}</td>
<td>{{CompatVersionUnknown}}</td>
<td>{{ CompatGeckoMobile("1.8.1") }}</td>
<td>{{CompatVersionUnknown}}</td>
<td>{{CompatVersionUnknown}}</td>
<td>{{CompatVersionUnknown}}</td>
</tr>
<tr>
<td>Propriedades com nome computado</td>
<td>{{CompatNo}}</td>
<td>{{CompatNo}}</td>
<td>{{ CompatGeckoMobile("34.0") }}</td>
<td>{{CompatNo}}</td>
<td>{{CompatNo}}</td>
<td>{{CompatNo}}</td>
</tr>
</tbody>
</table>
</div>
<h2 id="Veja_também">Veja também</h2>
<ul>
<li><a href="/en-US/docs/Web/JavaScript/Reference/Functions/set">setter</a></li>
<li>{{jsxref("Operators/delete", "delete")}}</li>
<li>{{jsxref("Object.defineProperty()")}}</li>
<li>{{jsxref("Object.defineGetter", "__defineGetter__")}}</li>
<li>{{jsxref("Object.defineSetter", "__defineSetter__")}}</li>
<li><a href="/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Defining_getters_and_setters">Defining Getters and Setters</a> in JavaScript Guide</li>
</ul>
|