Автотесты в JS
По-хорошему, разработка должна начинаться с BDD-документации. Это значит, что перед написанием кода мы пишем спецификацию, в которой опеределяем возможные результаты работы кода, и пишем его, подстраивая под них. Если код проходит тестирование в пограничных условиях - значит, всё замечательно.
Автотесты делают с помощью фреймворков. Самые популярные - Чай и Мока.
Они работают как NPM-модули, но могут и подключаться через браузер.
Простой модуль тестов через Моку состоит из трёх вложенных блоков:
- describe(string, callback())
- it(string, callback()
- assert.test(arg,[args])
Describe - блок для группировки тестов. Аргумент string - название блока, ничего более.
It - обертка конкретного теста. Первый аргумент - строка описания, что код должен делать при условиях, описанных тестом: it('should return false when...').
Assert - обращение к библиотеке функций, которая занимается непосредственно анализом результатов. У assert есть аналоги, и внутри assert есть множество разных методов. Здесь указан абстрактный метод "assert.test", идентичный настоящему "equal". Метод "equal" ожидаемо сравнивает первый аргумент со вторым. Осторожно! Метод использует нестрогое сравнение!
Другие методы assert:
https://nodejs.org/api/assert.html
По-хорошему, разработка должна начинаться с BDD-документации. Это значит, что перед написанием кода мы пишем спецификацию, в которой опеределяем возможные результаты работы кода, и пишем его, подстраивая под них. Если код проходит тестирование в пограничных условиях - значит, всё замечательно.
Автотесты делают с помощью фреймворков. Самые популярные - Чай и Мока.
Они работают как NPM-модули, но могут и подключаться через браузер.
Простой модуль тестов через Моку состоит из трёх вложенных блоков:
- describe(string, callback())
- it(string, callback()
- assert.test(arg,[args])
Describe - блок для группировки тестов. Аргумент string - название блока, ничего более.
It - обертка конкретного теста. Первый аргумент - строка описания, что код должен делать при условиях, описанных тестом: it('should return false when...').
Assert - обращение к библиотеке функций, которая занимается непосредственно анализом результатов. У assert есть аналоги, и внутри assert есть множество разных методов. Здесь указан абстрактный метод "assert.test", идентичный настоящему "equal". Метод "equal" ожидаемо сравнивает первый аргумент со вторым. Осторожно! Метод использует нестрогое сравнение!
Другие методы assert:
https://nodejs.org/api/assert.html
Элементарная математика
- Умножение - это совокупность тактов над каким-либо числом. Например, 6 * 3 = 6 + 6 + 6.
- Операцию выше можно назвать представлением. Представление - это описание числа как результата действий над другими числами. 18 = 6 * 3, 18 = 6 + 6 + 6, и 6 * 3 = 6 + 6 + 6.
- Разряд цифры - это ее позиция в числе. Возьмём 1024. В его разряде единиц - 4, в разряде десятков - 2, сотен - 0, тысяч - 1. Разряд говорит, сколько единиц, десятков, сотен, тысяч... и т.д. входят в число. Значением разряда могут быть только числа от 0 до 9, не считая дробей.
- Группировка чисел - это их представление как количества разрядных элементов. Скажем, 1024 = (100 * 10) + (10 * 2) * 4. Или 1000 + 20 + 4.
() => Разряды можно использовать для быстрого сложения больших чисел:
623 + 2422 = 2 + (6+4) + (2+2) + (2+3) = 3045.
В этом примере на третьей операции с конца произошло "переполнение разряда". Это значит, что при сложении значения разрядов сотен дали число больше 10. "Лишняя" цифра 1 переносится в следующий разряд, а в текущий записывается разряд единиц от этого числа.
Формально, такой способ перебрасывания лишних разрядов применяет для работы с числами представление их как групп разрядов. Применяется всё, что бысло описано выше.
В вычитании просиходит обратное - разряд переполняется в отрицательную сторону. Тогда просто заимствуем один из соседнего старшего разряда, записываем полученное число от в текущий разряд, а следующий считаем на единицу меньше:
756-699 = (6-6)+(14-9)+(16-9)=0+5+7=57.
() => Один из методов быстрого вычитания из чисел с большим количеством нулей на конце - вычитание единицы из таких чисел, затем классическое вычитание, затем прибавление единицы.
() => Если записать алгоритмически (на псевдо-JS) умножение на числа из первого разряда, равного 1, и остальными - равными 0, оно будет выглядеть так:
26 + 100 = 26.concat(00).
То есть мы просто переписываем нули из множителя во множимое. Или наоборот.
- Умножение - это совокупность тактов над каким-либо числом. Например, 6 * 3 = 6 + 6 + 6.
- Операцию выше можно назвать представлением. Представление - это описание числа как результата действий над другими числами. 18 = 6 * 3, 18 = 6 + 6 + 6, и 6 * 3 = 6 + 6 + 6.
- Разряд цифры - это ее позиция в числе. Возьмём 1024. В его разряде единиц - 4, в разряде десятков - 2, сотен - 0, тысяч - 1. Разряд говорит, сколько единиц, десятков, сотен, тысяч... и т.д. входят в число. Значением разряда могут быть только числа от 0 до 9, не считая дробей.
- Группировка чисел - это их представление как количества разрядных элементов. Скажем, 1024 = (100 * 10) + (10 * 2) * 4. Или 1000 + 20 + 4.
() => Разряды можно использовать для быстрого сложения больших чисел:
623 + 2422 = 2 + (6+4) + (2+2) + (2+3) = 3045.
В этом примере на третьей операции с конца произошло "переполнение разряда". Это значит, что при сложении значения разрядов сотен дали число больше 10. "Лишняя" цифра 1 переносится в следующий разряд, а в текущий записывается разряд единиц от этого числа.
Формально, такой способ перебрасывания лишних разрядов применяет для работы с числами представление их как групп разрядов. Применяется всё, что бысло описано выше.
В вычитании просиходит обратное - разряд переполняется в отрицательную сторону. Тогда просто заимствуем один из соседнего старшего разряда, записываем полученное число от в текущий разряд, а следующий считаем на единицу меньше:
756-699 = (6-6)+(14-9)+(16-9)=0+5+7=57.
() => Один из методов быстрого вычитания из чисел с большим количеством нулей на конце - вычитание единицы из таких чисел, затем классическое вычитание, затем прибавление единицы.
() => Если записать алгоритмически (на псевдо-JS) умножение на числа из первого разряда, равного 1, и остальными - равными 0, оно будет выглядеть так:
26 + 100 = 26.concat(00).
То есть мы просто переписываем нули из множителя во множимое. Или наоборот.
() => Алгоритм умножения многоразрядного числа на одноразрядное:
1. Умножаем значение разряда единиц множимого на множитель.
2. Если результат - многозначное число, пишем в результат его единицы, а значение разряда десятка перекидываем на следующий разряд множимого.
3. Умножаем следующий разряд.
4. Прибавляем к результату перекинутое значение в качестве единиц, записываем получившиеся единицы, а "лишний" разряд снова перебрасываем на следующий.
4. Повторяем, пока во множимом не кончатся числа. Последний "лишний" разряд записываем крайним слева.
1. Умножаем значение разряда единиц множимого на множитель.
2. Если результат - многозначное число, пишем в результат его единицы, а значение разряда десятка перекидываем на следующий разряд множимого.
3. Умножаем следующий разряд.
4. Прибавляем к результату перекинутое значение в качестве единиц, записываем получившиеся единицы, а "лишний" разряд снова перебрасываем на следующий.
4. Повторяем, пока во множимом не кончатся числа. Последний "лишний" разряд записываем крайним слева.
Методы элементарной математики - образцы оптимизации алгоритмов. Например, метод округления делимого и делителя в делении многозначных чисел значительно сокращает количество проверок частного. Мы сразу берем наиболее вероятное частное, проверяем, умножая его на делитель и сверяя с делимым, и по результату проверки увеличиваем/уменьшаем на один такт.
Вместо этого мы могли бы брать частное наугад, а машина - считать в цикле с нуля, что, очевидно, неоптимально при большой разнице между делимым и делителем.
Вместо этого мы могли бы брать частное наугад, а машина - считать в цикле с нуля, что, очевидно, неоптимально при большой разнице между делимым и делителем.
Простейшие законы математики
1. Сложение/умножение:
1.1. Сочетательный закон:
a +* b = b + a
1.2. Переместительный:
a +* b +* c = (a +* b) +* c = a +* (b +* c)
2. Умножение:
2.1. Распределительный закон:
(a + b) * c = a * c + b * c
Практический пример последнего:
6 * (3 + 6) =
6 * 9
или
18 + 36
Работает он и с разностью.
1. Сложение/умножение:
1.1. Сочетательный закон:
a +* b = b + a
1.2. Переместительный:
a +* b +* c = (a +* b) +* c = a +* (b +* c)
2. Умножение:
2.1. Распределительный закон:
(a + b) * c = a * c + b * c
Практический пример последнего:
6 * (3 + 6) =
6 * 9
или
18 + 36
Работает он и с разностью.
- Делитель - это число, на которое число делится без остатка.
В делители любого положительного числа больше ноля обычно входят 1 и само число:
12:1=12
12:12=1
В делители любого положительного числа больше ноля обычно входят 1 и само число:
12:1=12
12:12=1
- Кратное числа - это число, которое делится на взятое нами число без остатка. Например, 10 - кратное 5.
Это интересно: кратных у любого числа - бесконечно много.
() => Алгоритмы поиска признаков делимости:
- на десять:
num[last] === 0 && num >= 10
- на пять и два:
см. выше.
- на пять:
num[last] === 5 && num > 0
- на три:
(num[0] + num[1] + ... + num[last]) % 3 === 0
- на девять:
(num[0] + num[1] + ... + num[last]) % 9 === 0
Это интересно: кратных у любого числа - бесконечно много.
() => Алгоритмы поиска признаков делимости:
- на десять:
num[last] === 0 && num >= 10
- на пять и два:
см. выше.
- на пять:
num[last] === 5 && num > 0
- на три:
(num[0] + num[1] + ... + num[last]) % 3 === 0
- на девять:
(num[0] + num[1] + ... + num[last]) % 9 === 0
() => Алгоритм поиска всех делителей:
0. Простые множители: 2, 3, 5, 7.
1. Проверяем, делится ли число на наименьший простой множитель. Если нет, берем следующий.
2. Найдя подошедший, записываем его и делим на него число.
3. Повторяем, пока число не достигнет 1.
4. Удаляем повторяющиеся более двух раз.
5. Перемножаем между собой: как по два, так и большими порциями.
6. Получившиеся числа записываем в таблицу делителей.
0. Простые множители: 2, 3, 5, 7.
1. Проверяем, делится ли число на наименьший простой множитель. Если нет, берем следующий.
2. Найдя подошедший, записываем его и делим на него число.
3. Повторяем, пока число не достигнет 1.
4. Удаляем повторяющиеся более двух раз.
5. Перемножаем между собой: как по два, так и большими порциями.
6. Получившиеся числа записываем в таблицу делителей.
- НОД - это наибольший общий делитель двух чисел. Запись:
НОД(а, b)
() => Алгоритмы поиска НОД:
1. Перебор:
- получаем все делители a
- затем b
- сравниваем, пока не найдём наибольшее число, повторяющееся в обеих последовательностях.
2. Перемножение общих делителей:
- раскладываем два числа на простые множители
- находим общие
- перемножаем
- наибольшее полученное число будет НОД
3. Вычеркивание:
- раскладываем на простые множители
- вычеркиваем из последовательности все множители, которые не повторяются, пока последовательности не станут идентичными
- перемножаем оставшиеся множители
НОД(а, b)
() => Алгоритмы поиска НОД:
1. Перебор:
- получаем все делители a
- затем b
- сравниваем, пока не найдём наибольшее число, повторяющееся в обеих последовательностях.
2. Перемножение общих делителей:
- раскладываем два числа на простые множители
- находим общие
- перемножаем
- наибольшее полученное число будет НОД
3. Вычеркивание:
- раскладываем на простые множители
- вычеркиваем из последовательности все множители, которые не повторяются, пока последовательности не станут идентичными
- перемножаем оставшиеся множители
- НОК - это наименьшее общее кратное. Иначе говоря - наименьшее число, которое нацело делится на a и b. Есть три алгоритма его поиска, которые проще загуглить, чем переписывать.
Дроби бывают правильными и неправильными.
Правильные - те, у которых числитель (знак сверху) больше знаменателя (снизу).
Остальные - неправильные.
Из неправильных можно выделить целое.
Для 2|2 целое = 1.
Для 17|3 = 17 / 3 = 5 целых 2|3.
Смешанное число - целое с дробью - можно представить как неправильную дробь. Для этого умножим целое на знаменатель и прибавим числитель. Вот формула:
Правильные - те, у которых числитель (знак сверху) больше знаменателя (снизу).
Остальные - неправильные.
Из неправильных можно выделить целое.
Для 2|2 целое = 1.
Для 17|3 = 17 / 3 = 5 целых 2|3.
Смешанное число - целое с дробью - можно представить как неправильную дробь. Для этого умножим целое на знаменатель и прибавим числитель. Вот формула:
Два свойства дробей:
1. Если умножить числитель и знаменатель на одно и то же число, значение дроби не изменится. Это число называется дополнительным множителем.
2. Большинство дробей можно сократить. Для этого находим НОД для обоих и делим на него. Результатом станет сокращенная дробь.
Дроби из простых чисел сократить, очеивдно, нельзя.
1. Если умножить числитель и знаменатель на одно и то же число, значение дроби не изменится. Это число называется дополнительным множителем.
2. Большинство дробей можно сократить. Для этого находим НОД для обоих и делим на него. Результатом станет сокращенная дробь.
Дроби из простых чисел сократить, очеивдно, нельзя.
- Чтобы сложить десятичные дроби со знаменателями разной разрядности, нужно добить разницу между знаменателями нулями: 9, 455 + 7, 5 = 9,455 + 7, 500.
- Чтобы умножить десятичные дроби, нужно перемножить их, как обычные числа, и поставить запятую после стольких чисел справа, сколько всего знаков после запятой в числах, которые умножали
- Умножить дробь на целое? Легко. Принцип тот же: умножаем как обычные числа и ставим запятую после стольких знаков, сколько было в дроби.
- На 10, 100, 1000 и т.д.? Просто сдвигаем запятую вправо на количество нулей. 23,56656 * 100 = 2356,656.
- На 0,1 или 0,01 (и т.д.)? Сдвигаем запятую влево. 5,32 * 0,1 = 0,532.
- Чтобы разделить меньшее число на большее, например, 3 на 5, можно разделить его просто уголком. 3 < 5, пишем 0. 30 > 5, пишем 6. Разделяем знаком дроби. Итого 3 / 5 = 0.6.
- Чтобы разделить без остатка, нужно разделить уголком, как обычно, с остатком, а затем приписать к остатку нуль и разделить снова.
- Чтобы умножить десятичные дроби, нужно перемножить их, как обычные числа, и поставить запятую после стольких чисел справа, сколько всего знаков после запятой в числах, которые умножали
- Умножить дробь на целое? Легко. Принцип тот же: умножаем как обычные числа и ставим запятую после стольких знаков, сколько было в дроби.
- На 10, 100, 1000 и т.д.? Просто сдвигаем запятую вправо на количество нулей. 23,56656 * 100 = 2356,656.
- На 0,1 или 0,01 (и т.д.)? Сдвигаем запятую влево. 5,32 * 0,1 = 0,532.
- Чтобы разделить меньшее число на большее, например, 3 на 5, можно разделить его просто уголком. 3 < 5, пишем 0. 30 > 5, пишем 6. Разделяем знаком дроби. Итого 3 / 5 = 0.6.
- Чтобы разделить без остатка, нужно разделить уголком, как обычно, с остатком, а затем приписать к остатку нуль и разделить снова.
Forwarded from IT лекции
🔍 Теория игр вокруг нас
Спикер доступно расскажет все о теории игр, применении ее в повседневной жизни и о том, как не проиграть. Сперва вы вместе с Алексеем смоделируете «игру» непосредственно в аудитории, а затем разберёте следующие сюжеты:
1. Телеигра или задача о парковочных местах
2. Люксембург в Евросоюзе
3. Синдзо Абэ и Северная Корея
4. Парадокс Брайеса в Метрогородке (Москва)
5. Два парадокса Дональда Трампа
6. Рациональное безумие (снова Северная Корея)
Смотреть
@itlecture
Спикер доступно расскажет все о теории игр, применении ее в повседневной жизни и о том, как не проиграть. Сперва вы вместе с Алексеем смоделируете «игру» непосредственно в аудитории, а затем разберёте следующие сюжеты:
1. Телеигра или задача о парковочных местах
2. Люксембург в Евросоюзе
3. Синдзо Абэ и Северная Корея
4. Парадокс Брайеса в Метрогородке (Москва)
5. Два парадокса Дональда Трампа
6. Рациональное безумие (снова Северная Корея)
Смотреть
@itlecture
YouTube
Алексей Савватеев | Теория игр вокруг нас
18.05.2018
"Теория игр вокруг нас"
Презентация: https://goo.gl/NYSzPQ
Спикер доступно расскажет все о теории игр, применении ее в повседневной жизни и о том, как не проиграть. Сперва вы вместе с Алексеем смоделируете «игру» непосредственно в аудитории, а…
"Теория игр вокруг нас"
Презентация: https://goo.gl/NYSzPQ
Спикер доступно расскажет все о теории игр, применении ее в повседневной жизни и о том, как не проиграть. Сперва вы вместе с Алексеем смоделируете «игру» непосредственно в аудитории, а…
Мутабельность и иммутабельность.
- мутабельный объект - такой, который может быть изменен после создания.
- мутабельный метод - изменяющий непосредственно объект.
- иммутабельный объект - объект неизменяемый.
- иммутабельный метод возвращает копию объекта, а не изменяет его.
- мутабельный объект - такой, который может быть изменен после создания.
- мутабельный метод - изменяющий непосредственно объект.
- иммутабельный объект - объект неизменяемый.
- иммутабельный метод возвращает копию объекта, а не изменяет его.
Gulp:
- В версии 4.0.0+ есть функция gulp.series. Она выступает вторым аргументом для gulp.task, а принимает названия других тасков. Так создается единый таск для всех имеющихся.
Важно: таски выполняются асинхронно! Для синхронной обработки можно использовать коллбэки.
- Чтобы раскидать файлы по расширениям, не обязательно подключать плагин. Метод dest принимает функцию, которая, ориентируясь по объекту vynil, делает это из коробки:
.pipe(gulp.dest( (file) => {
if(file.extname === '.js') return 'js'
else if (file.extname === '.css') return 'css'
else return 'dest'
}
}
- В 4.0 есть функция parallels. Если series выполняет таски по-очереди, то parallels - синхронизирует их. Это простор для возможностей. Функции можно комбинировать: параллельно обрабатывать картинки, сжимать js и чистить html, а затем определять в проект в правильном порядке. Пример совмещения:
exports.build = series(
clean,
parallel(
cssTranspile,
series(jsTranspile, jsBundle)
),
parallel(cssMinify, jsMinify),
publish
);
- Есть в 4 версии и деление на приватные и публичные таски. Чтобы таск был приватным, его не надо объявлять на экспорт. Внутри файла-модуля он по-прежнему будет доступен.
- В версии 4.0.0+ есть функция gulp.series. Она выступает вторым аргументом для gulp.task, а принимает названия других тасков. Так создается единый таск для всех имеющихся.
Важно: таски выполняются асинхронно! Для синхронной обработки можно использовать коллбэки.
- Чтобы раскидать файлы по расширениям, не обязательно подключать плагин. Метод dest принимает функцию, которая, ориентируясь по объекту vynil, делает это из коробки:
.pipe(gulp.dest( (file) => {
if(file.extname === '.js') return 'js'
else if (file.extname === '.css') return 'css'
else return 'dest'
}
}
- В 4.0 есть функция parallels. Если series выполняет таски по-очереди, то parallels - синхронизирует их. Это простор для возможностей. Функции можно комбинировать: параллельно обрабатывать картинки, сжимать js и чистить html, а затем определять в проект в правильном порядке. Пример совмещения:
exports.build = series(
clean,
parallel(
cssTranspile,
series(jsTranspile, jsBundle)
),
parallel(cssMinify, jsMinify),
publish
);
- Есть в 4 версии и деление на приватные и публичные таски. Чтобы таск был приватным, его не надо объявлять на экспорт. Внутри файла-модуля он по-прежнему будет доступен.
- Команда gulp —tasks выводит дерево команд, а начиная с 4.0 - и синхронно-асинхронные цепочки series/parallels.
- Одной цепочке тасков может быть присвоено несколько значений, в зависимости от условий (if-else) и переданных в series/parallels тасков.
- Можно вызывать .src() прямо в цепочке между .src() и .dest(). Пример:
exports.default = function() {
return src('src/*.js')
.pipe(babel())
.pipe(src('vendor/*.js'))
.pipe(uglify())
.pipe(dest('output/'));
}
То же можно проделать и с .dest() - для сохранения состояния файла и обновления пути к нему.
- Есть два значимых режима .src(): Stream и Buffer. Buffer - стандартный режим: в нём метод считывает файлы в память, где и обрабатывает. Stream не читает файлы, что удобно для очень больших из них, вроде фильмов. В этом режиме файл разбивается на небольшие чанки и "течет" от входа к выходу, о чём красноречиво говорит его название. :) Переключить режимы можно опцией buffer.
- Negative globs - это строка, которую принимает src, в контексте отрицания:
gulp.src(['app/**/*.js', '!app/node_modules']).
Отрицательный glob должен следовать в массиве после положительного. В нём не должно быть неопределенных символов - так он наиболее производителен.
Чтобы не писать каждый раз глобальный объект gulp, а ограничиться src, dest и проч., нужно присвоить им всем require:
const { src, dest, series } = require('gulp');
- В сущности, globs - диалект регулярных выражений. Почитать про них можно тут: https://github.com/begin/globbing#what-is-globbing
- Одной цепочке тасков может быть присвоено несколько значений, в зависимости от условий (if-else) и переданных в series/parallels тасков.
- Можно вызывать .src() прямо в цепочке между .src() и .dest(). Пример:
exports.default = function() {
return src('src/*.js')
.pipe(babel())
.pipe(src('vendor/*.js'))
.pipe(uglify())
.pipe(dest('output/'));
}
То же можно проделать и с .dest() - для сохранения состояния файла и обновления пути к нему.
- Есть два значимых режима .src(): Stream и Buffer. Buffer - стандартный режим: в нём метод считывает файлы в память, где и обрабатывает. Stream не читает файлы, что удобно для очень больших из них, вроде фильмов. В этом режиме файл разбивается на небольшие чанки и "течет" от входа к выходу, о чём красноречиво говорит его название. :) Переключить режимы можно опцией buffer.
- Negative globs - это строка, которую принимает src, в контексте отрицания:
gulp.src(['app/**/*.js', '!app/node_modules']).
Отрицательный glob должен следовать в массиве после положительного. В нём не должно быть неопределенных символов - так он наиболее производителен.
Чтобы не писать каждый раз глобальный объект gulp, а ограничиться src, dest и проч., нужно присвоить им всем require:
const { src, dest, series } = require('gulp');
- В сущности, globs - диалект регулярных выражений. Почитать про них можно тут: https://github.com/begin/globbing#what-is-globbing
GitHub
GitHub - begin/globbing: Introduction to "globbing" or glob matching, a programming concept that allows "filepath expansion" and…
Introduction to "globbing" or glob matching, a programming concept that allows "filepath expansion" and matching using wildcards. - GitHub - begin/globbing: Int...
В JavaScript всё является объектом. Поэтому конструктор new Object ведет себя необычно: в зависимости от параметра он создает не пустой объект, а объект того типа данных, который ему был передан, с характерными методами. Такой конструктор внутри создает перевызов - new Object становится new Number.
const num = new Object(1);
num.constructor === Number // true
!!! На практике использование конструктора для создания объекта - антипаттерн. Ведь, когда вместо явно обозначенного аргумента ему передается переменная, код становится непредсказуемым и нечитаемым. Никогда нельзя забывать о читаемости кода коллегами.
const num = new Object(1);
num.constructor === Number // true
!!! На практике использование конструктора для создания объекта - антипаттерн. Ведь, когда вместо явно обозначенного аргумента ему передается переменная, код становится непредсказуемым и нечитаемым. Никогда нельзя забывать о читаемости кода коллегами.
!!! На практике конструкторы используются для штамповки однотипных объектов, чтобы не создавать каждый руками.
Их методы нужно выносить за пределы конструктора:
1. так удобнее расширять их. (заметка: узнать про обстановку дел в ЕS6/7);
2. метод, указанный прямо в конструкторе, первый из унаследованных от него объектов не получит.
Конструкторы нужно обязательно вызывать с ключевым словом new. Иначе контекст - this - присвоится в нём глобальному объекту.
Предотвратить ошибку можно так:
function new User(name) {
// code....
if(!(this.instanceof User)) {
return new User(name);
}
this. name = name;
}
}
Ключевое слово instanceof проверяет, каким конструктором создан объект. Слева указывается объект, справа - конструктор. Если значения не совпадают, выбрасывается false и на основе этого можно строить определенную логику.
!!! На практике это нужно, чтобы код работал безотказно у других разработчиков. Именно так работают встроенные конструкторы JS.
Их методы нужно выносить за пределы конструктора:
1. так удобнее расширять их. (заметка: узнать про обстановку дел в ЕS6/7);
2. метод, указанный прямо в конструкторе, первый из унаследованных от него объектов не получит.
Конструкторы нужно обязательно вызывать с ключевым словом new. Иначе контекст - this - присвоится в нём глобальному объекту.
Предотвратить ошибку можно так:
function new User(name) {
// code....
if(!(this.instanceof User)) {
return new User(name);
}
this. name = name;
}
}
Ключевое слово instanceof проверяет, каким конструктором создан объект. Слева указывается объект, справа - конструктор. Если значения не совпадают, выбрасывается false и на основе этого можно строить определенную логику.
!!! На практике это нужно, чтобы код работал безотказно у других разработчиков. Именно так работают встроенные конструкторы JS.