diff --git a/1-js/2-first-steps/7-types-intro/article.md b/1-js/2-first-steps/7-types-intro/article.md
index 6f7a242c..5ca4feff 100644
--- a/1-js/2-first-steps/7-types-intro/article.md
+++ b/1-js/2-first-steps/7-types-intro/article.md
@@ -1,4 +1,4 @@
-# Шесть типов данных
+# Шесть типов данных, typeof
В JavaScript существует несколько основных типов данных.
@@ -104,12 +104,65 @@ alert( x ); // "undefined"
Первые 5 типов называют *"примитивными"*.
-Особняком стоит шестой тип: *"объекты"*. К нему относятся, например, даты, функции, он используется для коллекций данных и для объявления более сложных сущностей.
+Особняком стоит шестой тип: *"объекты"*.
-Позже, в главе [про объекты](/object) мы вернёмся к этому типу и рассмотрим его принципиальные отличия от примитивов.
+Он используется для коллекций данных и для объявления более сложных сущностей.
+
+Объявляются объекты при помощи фигурных скобок `{...}`, например:
+
+```js
+var user = { name: "Вася" };
+```
+
+Мы подробно разберём способы объявления объектов и, вообще, работу с объектами, позже, в главе [](/object).
+
+## Оператор typeof [#type-typeof]
+
+Оператор `typeof` возвращает тип аргумента.
+
+У него есть два синтаксиса: со скобками и без:
+
+- Синтаксис оператора: `typeof x`.
+- Синтаксис функции: `typeof(x)`.
+
+
+Работают они одинаково, но первый синтаксис короче.
+
+**Результатом `typeof` является строка, содержащая тип:**
+
+```js
+typeof undefined // "undefined"
+
+typeof 0 // "number"
+
+typeof true // "boolean"
+
+typeof "foo" // "string"
+
+typeof {} // "object"
+
+*!*
+typeof null // "object" (1)
+*/!*
+
+*!*
+typeof function(){} // "function" (2)
+*/!*
+```
+
+Последние две строки помечены, потому что `typeof` ведет себя в них по-особому.
+
+
+- Результат `typeof null == "object"` -- это официально признанная ошибка в языке, которая сохраняется для совместимости. На самом деле `null` -- это не объект, а отдельный тип данных.
+- Функции мы пройдём чуть позже. Пока лишь заметим, что функции не являются отдельным базовым типом в JavaScript, а подвидом объектов. Но `typeof` выделяет функции отдельно, возвращая для них `"function"`. На практике это весьма удобно, так как позволяет легко определить функцию.
+
+
+К работе с типами мы также вернёмся более подробно в будущем, после изучения основных структур данных.
## Итого
-Есть 5 "примитивных" типов: `number`, `string`, `boolean`, `null`, `undefined` и 6-й тип -- объекты `object`.
+Есть 5 "примитивных" типов: `number`, `string`, `boolean`, `null`, `undefined` и 6-й тип -- объекты `object`.
-Очень скоро мы изучим их во всех деталях.
\ No newline at end of file
+Очень скоро мы изучим их во всех деталях.
+
+Оператор `typeof x` позволяет выяснить, какой тип находится в `x`, возвращая его в виде строки.
\ No newline at end of file
diff --git a/1-js/4-data-structures/12-typeof-duck-typing/1-format-date-polymorphic/_js.view/solution.js b/1-js/4-data-structures/12-typeof-duck-typing/1-format-date-polymorphic/_js.view/solution.js
deleted file mode 100644
index 5e5198e7..00000000
--- a/1-js/4-data-structures/12-typeof-duck-typing/1-format-date-polymorphic/_js.view/solution.js
+++ /dev/null
@@ -1,28 +0,0 @@
-function formatDate(date) {
- if (typeof date == 'number') {
- // перевести секунды в миллисекунды и преобразовать к Date
- date = new Date(date * 1000);
- } else if (typeof date == 'string') {
- // разобрать строку и преобразовать к Date
- date = date.split('-');
- date = new Date(date[0], date[1] - 1, date[2]);
- } else if (date.length) { // есть длина, но не строка - значит массив
- date = new Date(date[0], date[1], date[2]);
- }
- // преобразования для поддержки полиморфизма завершены,
- // теперь мы работаем с датой (форматируем её)
-
- var day = date.getDate();
- if (day < 10) day = '0' + day;
-
- var month = date.getMonth() + 1;
- if (month < 10) month = '0' + month;
-
- // взять 2 последние цифры года
- var year = date.getFullYear() % 100;
- if (year < 10) year = '0' + year;
-
- var formattedDate = day + '.' + month + '.' + year;
-
- return formattedDate;
-}
\ No newline at end of file
diff --git a/1-js/4-data-structures/12-typeof-duck-typing/1-format-date-polymorphic/_js.view/test.js b/1-js/4-data-structures/12-typeof-duck-typing/1-format-date-polymorphic/_js.view/test.js
deleted file mode 100644
index a458b62f..00000000
--- a/1-js/4-data-structures/12-typeof-duck-typing/1-format-date-polymorphic/_js.view/test.js
+++ /dev/null
@@ -1,18 +0,0 @@
-describe("formatDate", function() {
- it("читает дату вида гггг-мм-дд из строки", function() {
- assert.equal(formatDate('2011-10-02'), "02.10.11");
- });
-
- it("читает дату из числа 1234567890 (миллисекунды)", function() {
- assert.equal(formatDate(1234567890), "14.02.09");
- });
-
- it("читает дату из массива вида [гггг, м, д]", function() {
- assert.equal(formatDate([2014, 0, 1]), "01.01.14");
- });
-
- it("читает дату из объекта Date", function() {
- assert.equal(formatDate(new Date(2014, 0, 1)), "01.01.14");
- });
-
-});
\ No newline at end of file
diff --git a/1-js/4-data-structures/12-typeof-duck-typing/1-format-date-polymorphic/solution.md b/1-js/4-data-structures/12-typeof-duck-typing/1-format-date-polymorphic/solution.md
deleted file mode 100644
index ddf7c0aa..00000000
--- a/1-js/4-data-structures/12-typeof-duck-typing/1-format-date-polymorphic/solution.md
+++ /dev/null
@@ -1,55 +0,0 @@
-Для определения примитивного типа строка/число подойдет оператор [typeof](#type-typeof).
-
-Примеры его работы:
-
-```js
-//+ run
-alert( typeof 123 ); // "number"
-alert( typeof "строка" ); // "string"
-alert( typeof new Date() ); // "object"
-alert( typeof [] ); // "object"
-```
-
-Оператор `typeof` не умеет различать разные типы объектов, они для него все на одно лицо: `"object"`. Поэтому он не сможет отличить `Date` от `Array`.
-
-Используем для них утиную типизацию:
-
-Функция:
-
-```js
-//+ run
-function formatDate(date) {
- if (typeof date == 'number') {
- // перевести секунды в миллисекунды и преобразовать к Date
- date = new Date(date * 1000);
- } else if (typeof date == 'string') {
- // разобрать строку и преобразовать к Date
- date = date.split('-');
- date = new Date(date[0], date[1] - 1, date[2]);
- } else if (date.length) { // есть длина, но не строка - значит массив
- date = new Date(date[0], date[1], date[2]);
- }
- // преобразования для поддержки полиморфизма завершены,
- // теперь мы работаем с датой (форматируем её)
-
- var day = date.getDate();
- if (day < 10) day = '0' + day;
-
- var month = date.getMonth() + 1;
- if (month < 10) month = '0' + month;
-
- // взять 2 последние цифры года
- var year = date.getFullYear() % 100;
- if (year < 10) year = '0' + year;
-
- var formattedDate = day + '.' + month + '.' + year;
-
- return formattedDate;
-}
-
-alert( formatDate('2011-10-02') ); // 02.10.11
-alert( formatDate(1234567890) ); // 14.02.09
-alert( formatDate([2014, 0, 1]) ); // 01.01.14
-alert( formatDate(new Date(2014, 0, 1)) ); // 01.01.14
-```
-
diff --git a/1-js/4-data-structures/12-typeof-duck-typing/1-format-date-polymorphic/task.md b/1-js/4-data-structures/12-typeof-duck-typing/1-format-date-polymorphic/task.md
deleted file mode 100644
index 6dcf7974..00000000
--- a/1-js/4-data-structures/12-typeof-duck-typing/1-format-date-polymorphic/task.md
+++ /dev/null
@@ -1,26 +0,0 @@
-# Полиморфная функция formatDate
-
-[importance 5]
-
-Напишите функцию `formatDate(date)`, которая возвращает дату в формате `dd.mm.yy`.
-
-Ее первый аргумент должен содержать дату в одном из видов:
-
-- Как объект `Date`.
-- Как строку в формате `yyyy-mm-dd`.
-- Как число *секунд* с `01.01.1970`.
-- Как массив `[гггг, мм, дд]`, месяц начинается с нуля
-
-Для этого вам понадобится определить тип данных аргумента и, при необходимости, преобразовать входные данные в нужный формат.
-
-Пример работы:
-
-```js
-function formatDate(date) { /* ваш код */ }
-
-alert( formatDate('2011-10-02') ); // 02.10.11
-alert( formatDate(1234567890) ); // 14.02.09
-alert( formatDate([2014, 0, 1]) ); // 01.01.14
-alert( formatDate(new Date(2014, 0, 1)) ); // 01.01.14
-```
-
diff --git a/1-js/4-data-structures/12-typeof-duck-typing/article.md b/1-js/4-data-structures/12-typeof-duck-typing/article.md
deleted file mode 100644
index 7815b69c..00000000
--- a/1-js/4-data-structures/12-typeof-duck-typing/article.md
+++ /dev/null
@@ -1,184 +0,0 @@
-# Полиморфизм, typeof и утиная типизация
-
-В этой главе мы рассмотрим, как создавать *полиморфные* функции, то есть такие, которые по-разному обрабатывают аргументы, в зависимости от их типа. Например, функция вывода может по-разному форматировать числа и даты.
-
-Для реализации такой возможности нужен способ определить тип переменной.
-
-[cut]
-Как мы знаем, существует несколько *примитивных типов*:
-
-- `null`
-- Специальный тип, содержит только значение `null`.
-- `undefined`
-- Специальный тип, содержит только значение `undefined`.
-- `number`
-- Числа: `0`, `3.14`, а также значения `NaN` и `Infinity`
-- `boolean`
-- `true`, `false`.
-- `string`
-- Строки, такие как `"Мяу"` или пустая строка `""`.
-
-
-Все остальные значения, включая даты и массивы, являются объектами.
-
-## Оператор typeof [#type-typeof]
-
-Оператор `typeof` возвращает тип аргумента. У него есть два синтаксиса: со скобками и без:
-
-- Синтаксис оператора: `typeof x`.
-- Синтаксис функции: `typeof(x)`.
-
-
-Работают они одинаково, но первый синтаксис короче.
-
-**Результатом `typeof` является строка, содержащая тип:**
-
-```js
-typeof undefined // "undefined"
-
-typeof 0 // "number"
-
-typeof true // "boolean"
-
-typeof "foo" // "string"
-
-typeof {} // "object"
-
-*!*
-typeof null // "object"
-*/!*
-
-function f() { /* ... */ }
-typeof f // "function"
-*/!*
-```
-
-Последние две строки помечены, потому что `typeof` ведет себя в них по-особому.
-
-
-- Результат `typeof null == "object"` -- это официально признанная ошибка в языке, которая сохраняется для совместимости.
-
-На самом деле `null` -- это не объект, а примитив. Это сразу видно, если попытаться присвоить ему свойство:
-
-```js
-//+ run
-var x = null;
-x.prop = 1; // ошибка, т.к. нельзя присвоить свойство примитиву
-```
-
-
-- Для функции `f` значением `typeof f` является `"function"`. На самом деле функция не является отдельным базовым типом в JavaScript, все функции являются объектами, но такое выделение функций на практике удобно, так как позволяет легко определить функцию.
-
-
-**Оператор `typeof` надежно работает с примитивными типами, кроме `null`, а также с функциями. Но обычные объекты, массивы и даты для `typeof` все на одно лицо, они имеют тип `'object'`:**
-
-```js
-//+ run
-alert( typeof {} ); // 'object'
-alert( typeof [] ); // 'object'
-alert( typeof new Date ); // 'object'
-```
-
-Поэтому различить их при помощи `typeof` нельзя.
-
-## Утиная типизация
-
-Основная проблема `typeof` -- неумение различать объекты, кроме функций. Но есть и другой способ проверки типа.
-
-Так называемая "утиная типизация" основана на одной известной пословице: *"If it looks like a duck, swims like a duck and quacks like a duck, then it probably is a duck (who cares what it really is)"*.
-
-В переводе: *"Если это выглядит как утка, плавает как утка и крякает как утка, то, вероятно, это утка (какая разница, что это на самом деле)"*.
-
-Смысл утиной типизации -- в проверке необходимых методов и свойств.
-
-Например, у нас функция работает с массивами. Мы можем проверить, что объект -- массив, уточнив наличие метода `splice`, который, как известно, есть у всех массивов:
-
-```js
-//+ run
-var something = [1, 2, 3];
-
-if (something.splice) {
- alert( 'Это утка! То есть, массив!' );
-}
-```
-
-Обратите внимание -- в `if` мы не вызываем метод `something.splice()`, а пробуем получить само свойство `something.splice`. Для массивов оно всегда есть и является функцией, т.е. даст в логическом контексте `true`.
-
-Проверить на дату можно, определив наличие метода `getTime`:
-
-```js
-//+ run
-var x = new Date();
-
-if (x.getTime) {
- alert( 'Дата!' );
-}
-```
-
-С виду такая проверка хрупка, ее можно "сломать", передав похожий объект с тем же методом.
-
-Но как раз в этом и есть смысл утиной типизации: если объект похож на массив, у него есть методы массива, то будем работать с ним как с массивом (какая разница, что это на самом деле).
-
-[smart header="Метод `Array.isArray()`"]
-Для массивов есть специальный метод проверки: `Array.isArray(arr)`, который возвращает `true` только если `arr` -- массив:
-```js
-//+ run
-alert( Array.isArray([1,2,3]) ); // true
-alert( Array.isArray("not array")); // false
-```
-
-Этот метод уникален в своём роде, других аналогичных (типа `Object.isObject`, `Date.isDate`) -- нет.
-
-Если нужно удостовериться, что мы получили именно массив, а не нечто похожее на него -- можно использовать `Array.isArray`. Но при этом нужно отдавать себе отчёт, что этим мы одновременно ограничиваем применимость кода: "похожие на массив" данные теперь обрабатываться не будут. Решение зависит от конкретной ситуации.
-[/smart]
-
-
-
-
-
-## Полиморфизм
-
-Пример полиморфной функции -- `sayHi(who)`, которая будет говорить "Привет" своему аргументу, причём если передан массив -- то "Привет" каждому:
-
-```js
-//+ run
-function sayHi(who) {
-
- if (Array.isArray(who)) {
- who.forEach(sayHi);
- } else {
- alert( 'Привет, ' + who );
- }
-}
-
-// Вызов с примитивным аргументом
-sayHi("Вася"); // Привет, Вася
-
-// Вызов с массивом
-sayHi(["Саша", "Петя"]); // Привет, Саша... Петя
-
-// Вызов с вложенными массивами - тоже работает!
-sayHi(["Саша", "Петя", ["Маша", "Юля"]]); // Привет Саша..Петя..Маша..Юля
-```
-
-Здесь используется не "duck typing", а "жёсткая" проверка на массив. Можно было бы и поступить мягче -- проверить только наличие метода `forEach`:
-```js
-if (who.forEach) {
- ...
-}
-```
-
-## Итого
-
-Для написания полиморфных (это удобно!) функций нам нужна проверка типов.
-
-Для примитивов с ней отлично справляется оператор `typeof`.
-
-У него две особенности:
-
-- Он считает `null` объектом, это внутренняя ошибка в языке.
-- Для функций он возвращает `function`, по стандарту функция не считается базовым типом, но на практике это удобно и полезно.
-
-
-Там, где нужно различать объекты, обычно используется утиная типизация, то есть мы смотрим, есть ли в объекте нужный метод, желательно -- тот, который мы собираемся использовать.
-
diff --git a/1-js/5-functions-closures/5-closures-module/article.md b/1-js/5-functions-closures/5-closures-module/article.md
index 95958f90..134fa7b8 100644
--- a/1-js/5-functions-closures/5-closures-module/article.md
+++ b/1-js/5-functions-closures/5-closures-module/article.md
@@ -198,7 +198,7 @@ function work() {
Здесь нам не важно, какие, нас интересует именно как описана эта библиотека, как в ней применяется приём "модуль".
-Вот выдержка из исходного файла:
+Вот примерная выдержка из исходного файла:
```js
//+ run no-beautify
@@ -221,8 +221,7 @@ function work() {
// код функции size, пока что доступен только внутри
*/!*
function size(collection) {
- var length = collection ? collection.length : 0;
- return typeof length == 'number' ? length : Object.keys(collection).length;
+ return Object.keys(collection).length;
}
*!*
diff --git a/1-js/6-objects-more/4-descriptors-getters-setters/article.md b/1-js/6-objects-more/4-descriptors-getters-setters/article.md
index eb052300..f1453e79 100644
--- a/1-js/6-objects-more/4-descriptors-getters-setters/article.md
+++ b/1-js/6-objects-more/4-descriptors-getters-setters/article.md
@@ -243,9 +243,7 @@ alert( pete.age ); // 25
С обычными свойствами в коде меньше букв, они удобны, причины использовать функции пока нет.
-...Но рано или поздно может произойти что-то, что потребует более сложной логики.
-
-Например, формат данных изменился и теперь вместо возраста `age` хранится дата рождения `birthday`:
+...Но рано или поздно могут произойти изменения. Например, в `User` может стать более целесообразно вместо возраста `age` хранить дату рождения `birthday`:
```js
function User(name, birthday) {
@@ -263,12 +261,13 @@ var pete = new User("Петя", new Date(1987, 6, 1));
Добавление `get`-функции `age` позволяет обойти проблему легко и непринуждённо:
```js
-//+ run
+//+ run no-beautify
function User(name, birthday) {
this.name = name;
this.birthday = birthday;
*!*
+ // age будет высчитывать возраст по birthday
Object.defineProperty(this, "age", {
get: function() {
var todayYear = new Date().getFullYear();
@@ -280,10 +279,11 @@ function User(name, birthday) {
var pete = new User("Петя", new Date(1987, 6, 1));
-alert( pete.age ); // получает возраст из даты рождения
+alert( pete.birthday ); // и дата рождения доступна
+alert( pete.age ); // и возраст
```
-Таким образом, `defineProperty` позволяет нам использовать обычные свойства и, при необходимости, в любой момент заменить их на функции, сохраняя полную совместимость.
+Таким образом, `defineProperty` позволяет нам начать с обычных свойств, а в будущем, при необходимости, можно в любой момент заменить их на функции, реализующие более сложную логику.
## Другие методы работы со свойствами
diff --git a/1-js/6-objects-more/7-bind/article.md b/1-js/6-objects-more/7-bind/article.md
index 844d5c8d..4af65892 100644
--- a/1-js/6-objects-more/7-bind/article.md
+++ b/1-js/6-objects-more/7-bind/article.md
@@ -415,15 +415,9 @@ function mul(a, b) {
return a * b;
};
-function ask(question, correctAnswer, ok, fail) {
- var result;
- if (typeof correctAnswer == 'boolean') {
- result = confirm(question);
- } else {
- result = prompt(question, '');
- }
-
- if (result == correctAnswer) ok()
+function ask(question, answer, ok, fail) {
+ var result = prompt(question, '');
+ if (result.toLowerCase() == answer.toLowerCase()) ok();
else fail();
}
diff --git a/1-js/7-js-misc/1-class-property/article.md b/1-js/7-js-misc/1-class-property/article.md
deleted file mode 100644
index 34572c52..00000000
--- a/1-js/7-js-misc/1-class-property/article.md
+++ /dev/null
@@ -1,104 +0,0 @@
-# Секретное свойство [[Class]]
-
-Для встроенных объектов есть одна "секретная" возможность узнать их тип, которая связана с методом `toString`.
-
-Во всех встроенных объектах есть специальное свойство `[[Class]]`, в котором хранится информация о его типе или конструкторе.
-
-Оно взято в квадратные скобки, так как это свойство -- внутреннее. Явно получить его нельзя, но можно прочитать его "в обход", воспользовавшись методом `toString` из `Object`.
-
-[cut]
-
-## Получение [[Class]]
-
-Вернёмся к примеру, который видели раньше:
-
-```js
-//+ run
-var obj = {};
-alert( obj ); // [object Object]
-```
-
-**В выводе стандартного `toString` для объектов внутри `[object ...]` указано как раз значение `[[Class]]`.**
-
-Для обычного объекта это как раз и есть `"Object"`, но если бы такой `toString` запустить для даты, то будет `[object Date]`, для массивов -- `[object Array]` и т.п.
-
-К сожалению или к счастью, но большинство встроенных объектов в JavaScript имеют свой собственный метод `toString`: для массивов он выводит элементы через запятую, для дат -- строчное представление и так далее.
-
-То есть, просто вызов `[1,2,3].toString()` вернёт нам `1,2,3` и никакой информации про `[[Class]]`.
-
-Поэтому для получения `[[Class]]` мы одолжим функцию `toString` у стандартного объекта и запустим её в контексте тех значений, для которых нужно получить тип. В этом нам поможет метод `call`:
-
-```js
-//+ run
-var toClass = {}.toString; // (1)
-
-var arr = [1, 2];
-alert( toClass.call(arr) ); // (2) [object Array]
-
-var date = new Date;
-alert( toClass.call(date) ); // [object Date]
-
-var type = toClass.call(date).slice(8, -1); // (3)
-alert( type ); // Date
-```
-
-Разберем происходящее более подробно.
-
-
-- Можно переписать эту строку в две:
-
-```js
-var obj = {};
-var toClass = obj.toString;
-```
-
-Иначе говоря, мы создаём пустой объект `{}` и копируем ссылку на его метод `toString` в переменную `toClass`.
-
-**Для получения `[[Class]]` нужна именно внутренняя реализация `toString` стандартного объекта `Object`, другая не подойдёт.**
-- Вызываем скопированный метод в контексте нужного объекта `obj`.
-
-Мы могли бы поступить проще -- одолжить метод под другим названием:
-
-```js
-//+ run
-var arr = [1, 2];
-arr.toClass = {}.toString;
-
-alert( arr.toClass() ); // [object Array]
-```
-
-...Но зачем копировать лишнее свойство в объект? Синтаксис `toClass.call(arr)` делает то же самое, поэтому используем его.
-
-- Всё, класс получен. При желании можно убрать обёртку `[object ...]`, взяв подстроку вызовом `slice(8,-1)`.
-
-
-Метод также можно использовать с примитивами:
-
-```js
-//+ run
-alert( {}.toString.call(123) ); // [object Number]
-alert( {}.toString.call("строка") ); // [object String]
-```
-
-[warn header="Вызов `{}.toString` в консоли может выдать ошибку"]
-При тестировании кода в консоли вы можете обнаружить, что если ввести в командную строку `{}.toString.call(...)` -- будет ошибка. С другой стороны, вызов `alert( {}.toString... )` -- работает.
-
-Эта ошибка возникает потому, что фигурные скобки `{ }` в основном потоке кода интерпретируются как блок. Интерпретатор читает `{}.toString.call(...)` так:
-
-```js
-//+ no-beautify
-{ } // пустой блок кода
-.toString.call(...) // а что это за точка в начале? не понимаю, ошибка!
-```
-
-Фигурные скобки считаются объектом, только если они находятся в контексте выражения. В частности, оборачивание в скобки `( {}.toString... )` тоже сработает нормально.
-[/warn]
-
-## Итого
-
-
-- Свойство `[[Class]]` позволяет получить тип для встроенных объектов. Далее мы будем рассматривать создание своих объектов через функцию-конструктор, с ними `[[Class]]` не работает.
-- Для доступа к `[[Class]]` используется `{}.toString.call(obj).slice(8, -1)`.
-
-
-Обычно в JavaScript используется "утиная" типизация. Свойство `[[Class]]` -- самое надёжное средство проверки типа встроенных объектов, но обычно утиной типизации вполне хватает.
\ No newline at end of file