aboutsummaryrefslogtreecommitdiff
path: root/files/ru/web/javascript/reference/global_objects/eval/index.html
blob: ee90713bded1a517b83832eef8eb17bf28c1fe59 (plain)
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
---
title: eval()
slug: Web/JavaScript/Reference/Global_Objects/eval
tags:
  - JavaScript
  - NeedsUpdate
  - Reference
translation_of: Web/JavaScript/Reference/Global_Objects/eval
---
<div>{{jsSidebar("Objects")}}</div>

<div class="blockIndicator warning">
<p><strong>Warning:</strong> <font>Выполнение кода JavaScript с текстовой строки - это невероятный риск для безопасности. </font><font>Злоумышленнику слишком легко запустить какой угодно код, когда вы используете</font> <code>eval()</code>. Смотрите  <a href="#Не_используйте_eval_без_необходимости!">Никогда не изпользуте eval()!</a>, ниже.</p>
</div>

<p>Метод <code><strong>eval()</strong></code> выполняет JavaScript код, представленный строкой.</p>

<p>{{EmbedInteractiveExample("pages/js/globalprops-eval.html")}}</p>

<div class="hidden">
<p>The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> and send us a pull request.</p>
</div>

<h2 id="Синтаксис">Синтаксис</h2>

<pre class="syntaxbox notranslate"><code>eval(<em>string</em>)</code></pre>

<h3 id="Параметры">Параметры</h3>

<dl>
 <dt><code>string</code></dt>
 <dd>Строка, представленная JavaScript выражением, оператором или последовательностью операторов. Выражение может содержать переменные и свойства существующих объектов.</dd>
 <dt>
 <h3 id="Возвращаемое_значение">Возвращаемое значение</h3>
 </dt>
 <dd>Возвращает значение выполнения кода, переданного в функцию в виде строки. Если код не возвращает ничего - будет возвращено значение {{jsxref("undefined")}}.</dd>
</dl>

<h2 id="Описание">Описание</h2>

<p><code>eval()</code> - функция глобального объекта.</p>

<p>Аргумент функции <code>eval()</code> - строка. <code>eval()</code> исполняет содержащееся в строке выражение, один или несколько операторов  JavaScript. Не стоит вызывать <code>eval()</code> для определения значения арифметического выражения; JavaScript вычисляет их автоматически.</p>

<p><code>eval()</code> можно использовать для вычисления значения арифметического выражения, записанного в строковом виде, на более поздней стадии исполнения. Предположим, существует переменная <code>x</code>. Можно отложить вычисление выражения, в котором содержится <code>х</code>, если присвоить переменной это выражение в виде строки (допустим, "<code>3 * x + 2</code>"), а затем вызвать <code>eval()</code> в более поздней точке кода.</p>

<p>Если аргумент, переданный <code>eval()</code>, не является строкой, <code>eval() </code>возвращает его неизменным. В следующем примере определен конструктор <code>String</code>, и <code>eval()</code> не вычисляет значение выражения, записанного в строковом виде, а возвращает объект типа <code>String</code>.</p>

<pre class="brush:js notranslate">eval(new String("2 + 2")); // возвращает объект типа String, содержащий "2 + 2"
eval("2 + 2");             // возвращает 4
</pre>

<p>Это ограничение легко обойти при помощи <code>toString()</code>.</p>

<pre class="brush:js notranslate">var expression = new String("2 + 2");
eval(expression.toString());
</pre>

<p>Если вы используете <code>eval</code> косвенно, вызовом его через ссылку, а не просто <code>eval</code>, в<a href="http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.2"> ECMAScript 5</a> это работает в глобальной области видимости, а не в локальной; это значит, что <code>eval</code> будет вызван в глобальной области видимости, а код будет выполнен с отсутвием доступа к локальным переменным в пределах области видимости, где он был вызван.</p>

<pre class="brush:js notranslate">function test() {
  var x = 2, y = 4;
  console.log(eval("x + y"));  // Прямой вызов, использует локальную области видимости, результат - 6
  var geval = eval;
  console.log(geval("x + y")); // Непрямой вызов, использует глобальную область видимости, бросит ReferenceError, т.к. `x` - не определен
}
</pre>

<h2 id="Не_используйте_eval_без_необходимости!"><a name="dont-use-it"><code><font face="Open Sans, Arial, sans-serif">Н</font>е используйте eval без необходимости!</code></a></h2>

<p><code>eval()</code> - опасная функция, которая выполняет код, проходящий со всеми привилегиями вызывателя. Если вы запускаете <code>eval()</code> со строкой, на которую могут влиять злоумышленники, то вы можете запустить вредоносный код на устройство пользователя с правами вашей веб-страницы/расширения. Наиболее важно, код третьей стороны может видеть область видимости, в которой был вызван <code>eval()</code>, что может может привести к атакам, похожим на {{jsxref("Global_Objects/Function", "Function")}}.</p>

<p><code>Также eval(),</code>как правило, медленнее альтернатив, так как вызывает интерпретатор JS, тогда как многие другие конструкции оптимизированы современными JS движками.</p>

<p>Есть безопасные (и быстрые!) альтернативы <code>eval()</code> для общих случаев использования.</p>

<h3 id="Доступ_к_свойствам">Доступ к свойствам</h3>

<p>Вам не следует использовать <code>eval()</code>, чтобы конвертировать имена свойств в свойства. Рассматривая следующий пример, где свойство объекта используемое для доступа неизвестно до выполнения кода. Это можно сделать с  eval:</p>

<pre class="brush:js notranslate">var obj = { a: 20, b: 30 };
var propname = getPropName();  // возвращает "a" или "b"

eval( "var result = obj." + propname );
</pre>

<p>Однако, <code>eval()</code> здесь не нужен. По факту, использование здесь его удивляет. Вместо него используйте <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors" title="JavaScript/Reference/Operators/Member_Operators">доступ к свойствам</a>, который быстрее и безопаснее:</p>

<pre class="brush:js notranslate">var obj = { a: 20, b: 30 };
var propname = getPropName();  // возвращает "a" или "b"
var result = obj[ propname ];  //  obj[ "a" ] то же, что и obj.a
</pre>

<h3 id="Используйте_функции_вместо_исполнения_фрагментов_кода">Используйте функции вместо исполнения фрагментов кода</h3>

<p>У JavaScript <a class="external" href="http://en.wikipedia.org/wiki/First-class_function" title="http://en.wikipedia.org/wiki/First-class_function">функции первого класса</a>, что значит, что вы можете передавать функции как аргументы, хранить их в переменных или свойвах объектах и так далее. Многие DOM API созданы с учетом этого, так что вы можете (и вам следует) писать:</p>

<pre class="brush: js notranslate">// вместо setTimeout(" ... ", 1000) :
setTimeout(function() { ... }, 1000);

// вместо elt.setAttribute("onclick", "...") использовать:
elt.addEventListener("click", function() { ... } , false); </pre>

<p><a href="/en-US/docs/Web/JavaScript/Closures" title="JavaScript/Guide/Closures">Замыкания</a> также полезны как способ создания функций с параметрами без конкатенации строк.</p>

<h3 id="Разбор_JSON_конвертирование_строк_в_JavaScript_объекты">Разбор JSON (конвертирование строк в JavaScript объекты)</h3>

<p>Если строка, переданная в <code>eval()</code>, содержит данные (к примеру, массив: <code>"[1, 2, 3]"</code>), а не код, вам следует рассмотреть <a href="/en-US/docs/Glossary/JSON" title="JSON">JSON</a>, позволяющий строке использовать подмножество JavaScript синтаксиса для представления данных. Смотрите также: <a href="/en-US/docs/Downloading_JSON_and_JavaScript_in_extensions" title="Downloading_JSON_and_JavaScript_in_extensions">Загрузка JSON и JavaScript в расширениях</a>.</p>

<p>Заметьте, что синтаксис JSON ограничен в сравнении с JavaScript синтаксисом, многие валидные JavaScript литералы не распарсятся в JSON. К примеру, лишние запятые в конце выражений не разрешены в JSON, а имена свойств (ключи) в объектах должны быть в двойных кавычках. Будьте уверены использовать серилизацию JSON для создания строк, которые потом будут разбираться как JSON.</p>

<h3 id="Передавайте_данные_вместо_кода">Передавайте данные вместо кода</h3>

<p>К примеру, расширение, созданное изменять содержимое веб-страниц, должно иметь правила, определенные в <a href="/en-US/docs/XPath" title="XPath">XPath</a>, а не JS коде.</p>

<h3 id="Выполняйте_код_с_ограниченными_правами">Выполняйте код с ограниченными правами</h3>

<p>Если выполнять код всё-таки необходимо, желательно это делать с уменьшенными привелегиями. Этот совет подходит, главным образом, к расширениям и XUL приложениям, которые могут использовать <a href="/en-US/docs/Components.utils.evalInSandbox" title="Components.utils.evalInSandbox">Components.utils.evalInSandbox</a>.</p>

<h2 id="Примеры">Примеры</h2>

<h3 id="Использование_eval">Использование <code>eval</code></h3>

<p>В следующем коде оба выражения содержат <code>eval()</code>, возвращающий 42. Первое определяется строкой "<code>x + y + 1</code>"; второе - строкой "<code>42</code>".</p>

<pre class="brush:js notranslate">var x = 2;
var y = 39;
var z = "42";
eval("x + y + 1"); // возвращает 42
eval(z);           // вернёт 42
</pre>

<h3 id="Использование_eval_для_исполнения_строки_содержащей_операторы_JavaScript">Использование <code>eval</code> для исполнения строки, содержащей операторы JavaScript</h3>

<p>Следующий пример использует <code>eval()</code> для получения значения выражения <code>str</code>. Эта строка состоит из JavaScript выражений, печатающих в консоль, и, если x равен пяти, присвающих z значение 42, или 0 в противном случае. Когда второе выражение будет исполнено, <code>eval()</code> будет считать выражения выполненными, а также это установит значение выражению переменной z и вернет его.</p>

<pre class="brush:js notranslate">var x = 5;
var str = "if (x == 5) {console.log('z is 42'); z = 42;} else z = 0; ";

console.log("z is ", eval(str));</pre>

<h3 id="Последнее_выражение_выполняется">Последнее выражение выполняется</h3>

<p><code>eval()</code> вернет значение последнего выполняемого выражения</p>

<pre class="brush:js notranslate">var str = "if ( a ) { 1+1; } else { 1+2; }";
var a = true;
var b = eval(str);  // вернёт 2

console.log("b is : " + b);

a = false;
b = eval(str);  // вернёт 3

console.log("b is : " + b);</pre>

<h3 id="eval_как_строковое_определение_функции_включающее_и_как_префикс_и_суффикс"><code>eval</code> как строковое определение функции, включающее "(" и ")" как префикс и суффикс</h3>

<pre class="brush:js notranslate">var fctStr1 = "function a() {}"
var fctStr2 = "(function a() {})"
var fct1 = eval(fctStr1)  // вернёт undefined
var fct2 = eval(fctStr2)  // вернёт функцию
</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>ECMAScript 1st Edition.</td>
   <td>Стандарт</td>
   <td>Изначальное определение.</td>
  </tr>
  <tr>
   <td>{{SpecName('ES5.1', '#sec-15.1.2.1', 'eval')}}</td>
   <td>{{Spec2('ES5.1')}}</td>
   <td></td>
  </tr>
  <tr>
   <td>{{SpecName('ES6', '#sec-eval-x', 'eval')}}</td>
   <td>{{Spec2('ES6')}}</td>
   <td></td>
  </tr>
 </tbody>
</table>

<h2 id="Поддержка_браузерами">Поддержка браузерами</h2>

<div id="compat-mobile">
<div class="hidden">
<p>The compatibility table on this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
</div>

<p>{{Compat("javascript.builtins.eval")}}</p>
</div>

<h3 id="Gecko-специфичные_замечания">Gecko-специфичные замечания</h3>

<ul>
 <li>Исторически <code>eval()</code> имел второй необязательный аргумент, указывающий на то, в контексте какого объекта будет выполняться выражение. Этот аргумент не был стандартизован и был удален из SpiderMonkey в Gecko 1.9.1 (Firefox 3.5). См. {{bug(442333)}}.</li>
</ul>

<h2 id="Смотрите_также">Смотрите также</h2>

<ul>
 <li>{{jsxref("Global_Objects/uneval", "uneval()")}}</li>
 <li><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors">Доступ к свойствам</a></li>
</ul>