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
|
---
title: getter
slug: Web/JavaScript/Reference/Functions/get
tags:
- геттер
translation_of: Web/JavaScript/Reference/Functions/get
---
<div>{{jsSidebar("Functions")}}</div>
<p>Синтаксис <strong><code>get</code></strong> связывает свойство объекта с функцией, которая будет вызываться при обращении к этому свойству.</p>
<div>{{EmbedInteractiveExample("pages/js/functions-getter.html")}}</div>
<p class="hidden">Исходный код этого интерактивного примера хранится в GitHub репозитории. Если вы хотите внести свой вклад в проект интерактивных примеров, пожалуйста, клонируйте <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> и отправьте нам PR запрос.</p>
<h2 id="Синтаксис">Синтаксис</h2>
<pre class="syntaxbox">{get <var>prop</var>() { ... } }
{get [<var>expression</var>]() { ... } }</pre>
<h3 id="Параметры">Параметры</h3>
<dl>
<dt><code><var>prop</var></code></dt>
<dd>Имя свойства для привязывания к заданной функции.</dd>
<dt><code><var>expression</var></code></dt>
<dd>Начиная с ECMAScript 6, Вы также можете использовать выражения для вычисляемого имени свойства для привязки к заданной функции.</dd>
</dl>
<h2 id="Описание">Описание</h2>
<p>Иногда желательно разрешить доступ к свойству, которое возвращает динамически вычисляемое значение, или Вы можете захотеть отражать состояние внутренней переменной без необходимости использования явных вызовов методов. В JavaScript, это можно реализовать при помощи использования <em>геттера</em>.</p>
<p>Невозможно сделать так, чтобы геттер был привязан к свойству и одновременно чтобы это свойство действительно содержало значение, хотя можно использовать геттер и сеттер в сочетании, чтобы создать тип псевдо-свойство.</p>
<p>Учтите следующее при работе с синтаксисом <code>get</code>:</p>
<div>
<ul>
<li>Он может иметь идентификатор, который является либо числом, либо строкой;</li>
<li>Он должен иметь ровно 0 параметров (смотрите <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> для доп. информации);</li>
<li>Он не должен появляться в объектном литерале вместе с другим get или через ввод данных для того же свойства (<code>{ get x() { }, get x() { } }</code> и <code>{ x: ..., get x() { } }</code> запрещены).</li>
</ul>
</div>
<p>Геттер можно удалить при помощи оператора <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/delete" title="en/Core_JavaScript_1.5_Reference/Operators/Special_Operators/delete_Operator">delete</a></code>.</p>
<h2 id="Примеры">Примеры</h2>
<h3 id="Определение_геттера_на_новом_объекте_в_момент_инициализации_этого_объекта">Определение геттера на новом объекте в момент инициализации этого объекта</h3>
<p>Ниже создаётся псевдо-свойство <code>latest</code> для объекта <code>obj</code>, который выведет последний элемент массива в консоль лог.</p>
<pre class="brush: js">const obj = {
log: ['example','test'],
get latest() {
if (this.log.length === 0) return undefined;
return this.log[this.log.length - 1];
}
}
console.log(obj.latest); // "test"
</pre>
<p>Обратите внимание, что попытка присвоить значение <code>latest</code> не изменит его.</p>
<h3 id="Удаление_геттера_оператором_delete">Удаление геттера оператором delete</h3>
<p><code><font face="Open Sans, Arial, sans-serif">Если Вы хотите удалить геттер, используйте </font><a href="/en-US/docs/Web/JavaScript/Reference/Operators/delete">delete</a></code>:</p>
<pre class="brush: js">delete <var>obj</var>.latest;</pre>
<h3 id="Определение_геттера_на_уже_существующих_объектах_с_помощью_defineProperty">Определение геттера на уже существующих объектах с помощью <code>defineProperty</code></h3>
<p>Для добавления геттера к существующему объекту в любое время используйте <a class="external" href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty" rel="external nofollow">Object.defineProperty()</a>.</p>
<pre class="brush: js">const o = {a: 0};
Object.defineProperty(o, 'b', { get: function() { return this.a + 1; } });
console.log(o.b) // Runs the getter, which yields a + 1 (which is 1)
</pre>
<h3 id="Использование_вычисляемого_именованного_свойства">Использование вычисляемого именованного свойства</h3>
<div class="note">
<p><strong>Примечание:</strong> Вычисляемые свойства являются экспериментальной технологией, частью предложений спецификации ECMAScript 6, и массовой поддержки браузерами пока нет. Код ниже вызовет синтаксическую ошибку в неподдерживаемых средах.</p>
</div>
<pre class="brush: js">var expr = "foo";
var obj = {
get [expr]() { return "bar"; }
};
console.log(obj.foo); // "bar"</pre>
<h3 id="Умные_самостоятельно_перезаписывающиеся_ленивые_геттеры">Умные / самостоятельно перезаписывающиеся/ ленивые геттеры</h3>
<p>Геттеры дают нам возможность определять свойство объекта , но они не вычисляют значение этого свойства до тех пор, пока оно не станет доступно. Геттер откладывает стоимость вычисления значения до тех пор, пока это значение не станет нужно, и если оно никогда не понадобится, то вы никогда не заплатите.</p>
<p>Дополнительная техника оптимизации заключается в том, чтобы лениться или откладывать вычисление значения свойства и кэшировать его для дальнейшего доступа. Так поступают <strong>умные или <a href="https://en.wikipedia.org/wiki/Memoization">запоминающие</a> геттеры</strong>. Значение вычисляется в первый раз при вызове геттера и затем сохраняется в кэше так, что последующие обращения будут возвращать кэшированные значения без его пересчёта. Это полезно в следующих ситуациях:</p>
<ul>
<li>Если вычисление значения свойства дорого (занимает много оперативной памяти или процессорного времени, порождает рабочий поток, получает удалённый файл, и т. д.).</li>
<li>Если сейчас это значение не нужно. Оно будет использоваться позже, или в некоторых случаях оно не используется вообще.</li>
<li>Если оно используется, к нему будут обращаться несколько раз, и нет необходимости его пересчитывать, так как значение не будет изменено, или не должно пересчитываться.</li>
</ul>
<p>Значит, Вам не нужно использовать ленивый геттер для свойства, значение которого Вы собираетесь менять потому, что геттер не будет пересчитывать значение.</p>
<p>В следующем примере у объекта есть геттер как собственное свойство. При получении свойства, свойство удаляется из объекта и вновь добавляется, но в этот раз неявно, как свойство с данными. В итоге значение возвращается.</p>
<pre class="brush: js">get notifier() {
delete this.notifier;
return this.notifier = document.getElementById("bookmarked-notification-anchor");
},</pre>
<p>Для Firefox смотрите также модуль XPCOMUtils.jsm , который определяет функцию <code><a href="/en-US/docs/Mozilla/JavaScript_code_modules/XPCOMUtils.jsm#defineLazyGetter()">defineLazyGetter()</a></code>.</p>
<h3 id="get_и_defineProperty"><code>get</code> и <code>defineProperty</code></h3>
<p>Использование ключевого слова <code>get</code> и {{jsxref("Object.defineProperty()")}} даёт похожие результаты, но при использовании в {{jsxref("classes")}} между ними есть тонкая разница.</p>
<p>При использовании <code>get</code> свойство будет определено в прототипе объекта, в то время, как при использовании {{jsxref ("Object.defineProperty ()")}} свойство будет определено в экземпляре, к которому применяется.</p>
<pre class="brush: js">class Example {
get hello() {
return 'world';
}
}
const obj = new Example();
console.log(obj.hello);
// "world"
console.log(Object.getOwnPropertyDescriptor(obj, 'hello'));
// undefined
console.log(Object.getOwnPropertyDescriptor(Object.getPrototypeOf(obj), 'hello'));
// { configurable: true, enumerable: false, get: function get hello() { return 'world'; }, set: undefined }</pre>
<h2 id="Спецификации">Спецификации</h2>
<table class="standard-table">
<tbody>
<tr>
<th scope="col">Спецификация</th>
<th scope="col">Статус</th>
<th scope="col">Комментарии</th>
</tr>
<tr>
<td>{{SpecName('ES5.1', '#sec-11.1.5', 'Object Initializer')}}</td>
<td>{{Spec2('ES5.1')}}</td>
<td>Первоначальное определение.</td>
</tr>
<tr>
<td>{{SpecName('ES6', '#sec-method-definitions', 'Method definitions')}}</td>
<td>{{Spec2('ES6')}}</td>
<td>Добавлено вычисляемое именное свойство.</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" name="Browser_compatibility">Совместимость с браузерами</h2>
<p>{{Compat("javascript.functions.get")}}</p>
<h2 id="Смотрите_также">Смотрите также</h2>
<ul>
<li><a href="/en-US/docs/Web/JavaScript/Reference/Functions/set">сеттер</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>
|