You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 1-js/6-objects-more/2-object-conversion/4-object-types-conversion-questions/solution.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -30,4 +30,4 @@ alert( [1,[0],2][1] );
30
30
Квадратные скобки после массива/объекта обозначают не другой массив, а взятие элемента.
31
31
</li>
32
32
<li>Каждый объект преобразуется к примитиву. У встроенных объектов `Object` нет подходящего `valueOf`, поэтому используется `toString`, так что складываются в итоге строковые представления объектов.</li>
Copy file name to clipboardExpand all lines: 1-js/6-objects-more/2-object-conversion/article.md
+24Lines changed: 24 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -234,5 +234,29 @@ if ( value ) {
234
234
Полный алгоритм преобразований есть в спецификации EcmaScript, смотрите пункты [11.8.5](http://es5.github.com/x11.html#x11.8.5), [11.9.3](http://es5.github.com/x11.html#x11.9.3), а также [9.1](http://es5.github.com/x9.html#x9.1) и [9.3](http://es5.github.com/x9.html#x9.3).
235
235
236
236
237
+
Заметим, для полноты картины, что некоторые тесты знаний в интернет предлагают вопросы типа:
238
+
```js
239
+
{}[0] // чему равно?
240
+
{} + {} // а так?
241
+
```
242
+
243
+
Если вы запустите эти выражения в консоли, то результат может показаться странным. Подвох здесь в том, что если фигурные скобки `{...}` идут не в выражении, а в основном потоке кода, то JavaScript считает, что это не объект, а "блок кода" (как `if`, `for`, но без оператора, просто группировка команд вместе, используется редко).
244
+
245
+
Вот блок кода с командой:
246
+
```js
247
+
//+run
248
+
{
249
+
alert("Блок")
250
+
}
251
+
```
252
+
253
+
А если команду изъять, то будет пустой блок `{}`, который ничего не делает. Два примера выше как раз содержат пустой блок в начале, который ничего не делает. Иначе говоря:
254
+
```js
255
+
{}[0] // то же что и: [0]
256
+
{} + {} // то же что и: + {}
257
+
```
258
+
259
+
То есть, такие вопросы -- не на преобразование типов, а на понимание, что если `{ ... }` находится вне выражений, то это не объект, а блок.
Copy file name to clipboardExpand all lines: 1-js/6-objects-more/7-bind/article.md
+75-14Lines changed: 75 additions & 14 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -116,25 +116,57 @@ function bind(func, context) {
116
116
Посмотрим, что она делает, как работает, на таком примере:
117
117
118
118
```js
119
-
var oldSayHi =user.sayHi;
120
-
var sayHi =bind(oldSayHi, user);
119
+
//+ run
120
+
functionf() { alert(this); }
121
+
122
+
var g =bind(f, "Context");
123
+
g(); // Context
121
124
```
122
125
123
-
Результатом `bind(oldSayHi, user)`, как видно из кода, будет анонимная функция `(*)`, вот она отдельно:
126
+
То есть, `bind(f, "Context")` привязывает `"Context"` в качестве `this` для `f`.
127
+
128
+
Посмотрим, за счёт чего это происходит.
129
+
130
+
Результатом `bind(f, "Context")`, как видно из кода, будет анонимная функция `(*)`.
131
+
132
+
Вот она отдельно:
124
133
125
134
```js
126
135
function() { // (*)
127
-
returnoldSayHi.apply(user, arguments);
136
+
returnfunc.apply(context, arguments);
128
137
};
129
138
```
130
139
131
-
Она запишется в переменную `sayHi`.
140
+
Если подставить наши конкретные аргументы, то есть `f` и `"Context"`, то получится так:
141
+
142
+
```js
143
+
function() { // (*)
144
+
returnf.apply("Context", arguments);
145
+
};
146
+
```
147
+
148
+
Эта функция запишется в переменную `g`.
149
+
150
+
Далее, если вызвать `g`, то вызов будет передан в `f`, причём `f.apply("Context", arguments)` передаст в качестве контекста `"Context"`, который и будет выведен.
151
+
152
+
Если вызвать `g` с аргументами, то также будет работать:
153
+
154
+
```js
155
+
//+ run
156
+
functionf(a, b) {
157
+
alert(this);
158
+
alert(a + b);
159
+
}
160
+
161
+
var g =bind(f, "Context");
162
+
g(1, 2); // Context, затем 3
163
+
```
132
164
133
-
Далее, если её вызвать с какими-то аргументами, например `sayHi("Петя")`, то она "передаёт вызов" в `oldSayHi` -- используется `.apply(user, arguments)`, чтобы передать в качестве контекста `user` (он будет взят из замыкания) и текущие аргументы `arguments`.
165
+
Аргументы, которые получила `g(...)`, передаются в `f` также благодаря методу `.apply`.
134
166
135
-
Иными словами, в результате вызова `bind(func, context)` мы получаем "функцию-обёртку", которая прозрачно передаёт вызов в `func`, с теми же аргументами, но фиксированным контекстом `context`.
167
+
**Иными словами, в результате вызова `bind(func, context)` мы получаем "функцию-обёртку", которая прозрачно передаёт вызов в `func`, с теми же аргументами, но фиксированным контекстом `context`.**
Вызов `bind(user.sayHi, user)` возвращает такую функцию-обёртку, которая гарантированно вызовет `user.sayHi`в контексте`user`. В данном случае, через 1000мс.
193
+
Вызов `bind(user.sayHi, user)` возвращает такую функцию-обёртку, которая привязывает вызовет `user.sayHi`к контексту`user`. Она будет вызвана через 1000мс.
162
194
163
-
Причём, если вызвать обёртку с аргументами -- они пойдут в `user.sayHi` без изменений, фиксирован лишь контекст.
195
+
Полученную обёртку можно вызвать и с аргументами -- они пойдут в `user.sayHi` без изменений, фиксирован лишь контекст.
164
196
165
197
```js
166
198
//+ run
167
199
var user = {
168
200
firstName:"Вася",
169
-
sayHi:function(who) {
201
+
*!*
202
+
sayHi:function(who) { // здесь у sayHi есть один аргумент
203
+
*/!*
170
204
alert(this.firstName+": Привет, "+ who);
171
205
}
172
206
};
173
207
174
208
var sayHi =bind(user.sayHi, user);
175
209
176
210
*!*
211
+
// контекст Вася, а аргумент передаётся "как есть"
В современном JavaScript (или при подключении библиотеки [es5-shim](https://github.com/kriskowal/es5-shim) для IE8-) у функций уже есть встроенный метод [bind](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind), который мы можем использовать.
189
224
190
-
Он позволяет получить обёртку, которая привязывает функцию не только к нужному контексту но, если нужно, то и к аргументам.
225
+
Он работает примерно так же, как `bind`, который описан выше.
191
226
192
-
Синтаксис `bind`:
227
+
Изменения очень небольшие:
228
+
229
+
```js
230
+
//+ run
231
+
functionf(a, b) {
232
+
alert(this);
233
+
alert(a + b);
234
+
}
235
+
236
+
*!*
237
+
// вместо
238
+
// var g = bind(f, "Context");
239
+
var g =f.bind("Context");
240
+
*/!*
241
+
g(1, 2); // Context, затем 3
242
+
```
243
+
244
+
Синтаксис встроенного `bind`:
193
245
194
246
```js
195
247
var wrapper =func.bind(context[, arg1, arg2...])
@@ -199,7 +251,7 @@ var wrapper = func.bind(context[, arg1, arg2...])
199
251
<dt>`func`</dt>
200
252
<dd>Произвольная функция</dd>
201
253
<dt>`context`</dt>
202
-
<dd>Обертка `wrapper` будет вызывать функцию с контекстом `this = context`.</dd>
254
+
<dd>Контекст, который привязывается к `func`</dd>
203
255
<dt>`arg1`, `arg2`, ...</dt>
204
256
<dd>Если указаны аргументы `arg1, arg2...` -- они будут прибавлены к каждому вызову новой функции, причем встанут *перед* теми, которые указаны при вызове.</dd>
Далее мы будем использовать именно встроенный метод `bind`.
229
281
282
+
[warn header="bind не похож call/apply"]
283
+
Методы `bind` и `call/apply` близки по синтаксису, но есть важнейшее отличие.
284
+
285
+
Методы `call/apply` вызывают функцию с заданным контекстом и аргументами.
286
+
287
+
А `bind` не вызывает функцию. Он только возвращает "обёртку", которую мы можем вызвать позже, и которая передаст вызов в исходную функцию, с привязанным контекстом.
288
+
[/warn]
289
+
230
290
[smart header="Привязать всё: `bindAll`"]
231
291
Если у объекта много методов и мы планируем их активно передавать, то можно привязать контекст для них всех в цикле:
232
292
@@ -241,6 +301,7 @@ for(var prop in user) {
241
301
В некоторых JS-фреймворках есть даже встроенные функции для этого, например [_.bindAll(obj)](http://lodash.com/docs#bindAll).
242
302
[/smart]
243
303
304
+
244
305
## Карринг
245
306
246
307
До этого мы говорили о привязке контекста. Теперь пойдём на шаг дальше. Привязывать можно не только контекст, но и аргументы. Используется это реже, но бывает полезно.
0 commit comments