
JavaScript — это уникальный язык программирования, обладающий некоторыми странными и причудливыми особенностями, которых нет в других языках программирования. В этой статье мы рассмотрим 10 странных и странных вещей, связанных с языком JavaScript.
- Автоматическая вставка точки с запятой
 Одной из самых известных особенностей JavaScript является автоматическая вставка точки с запятой. В отличие от большинства языков программирования, JavaScript не требует точки с запятой в конце каждого оператора. Если вы пропустите точку с запятой, JavaScript часто вставит ее вместо вас, что иногда может привести к неожиданному поведению.
Например:
function foo() {
  return
  {
    bar: 'hello'
  };
}
console.log(foo()); // undefined
В этом примере объектный литерал обрабатывается как отдельный оператор и не возвращается функцией, что приводит к выводу «undefined» вместо ожидаемого объекта.
2.  Приведение типов
JavaScript — это язык с динамической типизацией, что означает, что переменные могут содержать значения разных типов.  Однако JavaScript также имеет странное поведение приведения типов, которое иногда может приводить к неожиданным результатам.
console.log('5' + 5); // "55"
console.log('5' - 5); // 0
В этом примере первая строка объединяет две строки, а вторая строка вычитает 5 из строки «5», в результате чего получается число 0.
3.  NaN
В JavaScript есть специальное значение, называемое NaN (не число), которое представляет собой результат неопределенной или непредставимой математической операции.  Однако NaN не равно никакому значению, в том числе самому себе, что может сбивать с толку.
console.log(NaN === NaN); // false console.log(NaN == NaN); // false
В этом примере оба сравнения возвращают false, даже если они сравнивают NaN с самим собой.
4. Правдивые и ложные значения
В JavaScript есть концепция истинных и ложных значений, то есть значений, которые рассматриваются как истинные или ложные в логических выражениях.  Иногда это может привести к неожиданному поведению.
Например:
console.log(Boolean('')); // false
console.log(Boolean(0)); // false
console.log(Boolean(null)); // false
console.log(Boolean(undefined)); // false
В этом примере все значения считаются ложными, даже если они не являются явно ложными.
5.  Глобальная область
В JavaScript переменные, объявленные вне функции, автоматически помещаются в глобальную область.  Иногда это может привести к неожиданному поведению, особенно в больших приложениях.
Например:
var x = 10;
function foo() {
  var x = 5;
}
foo();
console.log(x); // 10
В этом примере переменная x внутри функции является локальной переменной и не влияет на глобальную переменную с тем же именем.
6.  Подъем
В JavaScript есть концепция, называемая подъемом, которая означает, что объявления переменных и функций перемещаются в верхнюю часть соответствующих областей видимости.  Иногда это может привести к неожиданному поведению, если вы не будете осторожны.
foo(); // "hello"
function foo() {
  console.log('hello');
}
В этом примере функция вызывается до ее объявления, но она все еще работает из-за подъема.
7.  Динамические свойства объектов
JavaScript позволяет добавлять и удалять свойства объектов во время выполнения, что может быть полезно, но также может привести к неожиданному поведению.
Например:
var obj = {};
obj.foo = 'hello';
console.log(obj); // {foo: "hello"}
delete obj.foo;
console.log(obj); // {}
В этом примере мы добавляем свойство к объекту, а затем удаляем его, в результате чего получается пустой объект.
8.  Наследование прототипов
JavaScript использует модель наследования на основе прототипов, которая отличается от классической модели наследования, используемой во многих других языках программирования.  В этой модели объекты могут наследовать свойства и методы от других объектов, известных как их прототипы.
Например:
function Animal(name) {
  this.name = name;
}
Animal.prototype.speak = function() {
  console.log('Animal speaking');
}
function Dog(name) {
  this.name = name;
}
Dog.prototype = new Animal();
Dog.prototype.bark = function() {
  console.log('Woof!');
}
var fido = new Dog('Fido');
fido.bark(); // "Woof!"
fido.speak(); // "Animal speaking"
В этом примере мы создаем функцию-конструктор Animal и добавляем метод к ее прототипу. Затем мы создаем функцию-конструктор Dog и устанавливаем ее прототип в экземпляр Animal, позволяя объектам Dog наследовать методы Animal. Наконец, мы создаем новый объект Dog и вызываем оба метода: bark и speak.
9.  Объекты-функции
В JavaScript функции являются объектами первого класса, что означает, что их можно передавать в качестве аргументов другим функциям, возвращать из функций в виде значений и хранить в переменных.
Например:
function add(a, b) {
  return a + b;
}
var multiply = function(a, b) {
  return a * b;
}
function calculator(operation, a, b) {
  return operation(a, b);
}
console.log(calculator(add, 2, 3)); // 5
console.log(calculator(multiply, 2, 3)); // 6
В этом примере мы определяем две функции и сохраняем одну из них в переменной. Затем мы определяем функцию калькулятора, которая принимает функцию операции в качестве аргумента и использует ее для вычисления результата.
10.  Асинхронное программирование
JavaScript — это однопоточный язык, но он также поддерживает асинхронное программирование с использованием обратных вызовов, промисов и async/await.  Это позволяет коду JavaScript выполнять неблокирующие операции ввода-вывода и повышать производительность.
Например:
function fetchData(url) {
  return fetch(url)
    .then(function(response) {
      return response.text();
    });
}
fetchData('https://jsonplaceholder.typicode.com/posts/1')
  .then(function(response) {
    console.log(response);
});
В этом примере мы определяем функцию fetchData, которая использует метод fetch для извлечения данных из URL-адреса и возвращает обещание, которое разрешается текстом ответа.  Затем мы вызываем функцию fetchData с URL-адресом и используем обещание, возвращенное fetchData, для записи ответа на консоль.
Обратите внимание, что метод fetch возвращает обещание, которое разрешается с помощью объекта Response, для которого мы затем вызываем метод text, чтобы получить текст ответа.  Мы используем метод then для обработки промиса, возвращенного fetchData, и записываем текст ответа в консоль.
Заключение
JavaScript — уникальный и мощный язык, но он также имеет некоторые странные и причудливые особенности, которые может быть трудно понять. Поняв эти странные и странные вещи в JavaScript, вы сможете стать лучшим разработчиком JavaScript и избежать распространенных ловушек и ошибок.
 
                                                                     
                                                                     
                                                                    