Привет, читатели, я фронтенд-разработчик, работаю с JS уже 3 года и планирую почти столько же времени читать YDKJS Кайла Симпсона, но так и не добился успеха, это еще одна попытка, я буду подытоживать книги. в этих сообщениях, когда я их читаю.

Это первый пост, и в нем я делюсь своими знаниями из первой книги серии «Вверх и вперед».

Эта книга больше похожа на введение в JavaScript, и в ней подчеркивается, как глубокое понимание JavaScript может принести пользу людям, которые его используют, но не знакомы с концепциями, функциями и предостережениями языка или предпочитают игнорировать то, что они не понимают и продолжать работать с неполным знанием языка, которое у них есть.
Некоторые утверждения из книги, которые звонят мне в колокольчик,

Один из самых важных уроков, которые вы можете извлечь из написания кода, заключается в том, что он предназначен не только для компьютера. Код так же важен для разработчика, если не больше, как и для компилятора.

Ваш компьютер заботится только о машинном коде, наборе двоичных нулей и единиц, который получается при компиляции. Вы можете написать почти бесконечное количество программ, которые выдают одну и ту же серию нулей и единиц. Выбор, который вы делаете в отношении написания своей программы, важен не только для вас, но и для других членов вашей команды и даже для вас самих в будущем.

В предисловии к книге подчеркивается важность понимания сложных моментовJavaScript. Я верю в это и, таким образом, пытаюсь понять эти так называемые трудные моменты с помощью этих книг.

Первая глава представляет собой введение в программирование и JS, здесь есть базовое введение в эти понятия,
переменные, условные операторы, выражения, операторы, циклы, функции, области видимости.

Одним из ключевых моментов этой главы является то, что JavaScript динамически типизируется.

В некоторых языках программирования есть переменные, которые могут содержать только определенный тип значения, например число, строку и т. д., называемые языками со статической типизацией.

В то время как некоторые делают упор на тип значений, а не на переменные, это означает, что переменная может содержать значение любого типа в любое время.
JavaScript следует за вторым, поэтому он динамически типизирован.

Что такое типы в JavaScript?

«В JavaScript есть типизированные значения, а не типизированные переменные».
В JavaScript есть 7 типов
number, string, boolean, object, null, undefined, symbol.
Любая переменная может содержать значение любого из этих типов в любое время.

Одна давняя ошибка в JavaScript, которая, вероятно, никогда не будет исправлена, заключается в том, что typeof nullвозвращает объект и нет ноль.

objectявляется одним из наиболее полезных типов значений.
Есть пара других очень полезных и часто используемых типов, arrayи function, это не типы как таковые, а специализированные или подтипы типа object.

Встроенные методы типов

Встроенные типы и подтипы имеют поведение, представленное в виде свойств и методов, например, тип string имеет открытый метод toUpperCase(), который возвращает новую строку, которая является прописной версией строки, в которой toUpperCase() был вызван.

let x = "hello world"; // x has a string type value stored in it
let y = x.toUpperCase() //y now has string "HELLO WORLD" stored in it

В этом примере много чего происходит внутри, для примитивных типов string,number,boolean есть объекты-оболочки String,Number,Booleanсоответственно, у которых это поведение представлено как методы и свойства.

Когда вы пытаетесь использовать это поведение для примитивных значений, JavaScript автоматически упаковывает значение в соответствующий объект-оболочку.

Преобразование типов в JavaScript (Приведение)

Типы в JavaScript можно преобразовывать из одного типа в другой, этот процесс преобразования типов называется приведением.
Приведение
может быть неявным или явное, когда из кода понятно, что будет преобразование - это явное приведение, например

let numberString = "55"; //typeof numberString == "string"
let number = Number(numberString); //typeof number == "number"
// the string is converted to number explicitly

когда из кода не ясно, что происходит преобразование значения, это называется неявным приведением, например

let numberString = "55"; //typeof numberString == "string"
let twiceNumber = numberString * 2; //typeof twiceNumber == "number"
//the string is converted to a number implicitly

Истинные и ложные значения в JavaScript

При преобразовании других типов значений в логический тип только 6 значений преобразуются в false,эти значения, включая false, называются ложнымизначениями.

""
0
-0
undefined
null
NaN
false

только эти значения (кроме false) преобразуются в false во время приведения, все остальные значения преобразуются в true.

Сравнение значений в JavaScript

Существует два типа сравнений: равенство и неравенство.
Результат любого сравнения строго логическое значение, т. е. true или false, независимо от сравниваемых типов.

Операторы сравнения, доступные в JavaScript:

------------- equality operators --------------

== // loose equality
!= // loose non-equality
=== // strict equality
!== // strict non-equality

------------- inequality operators ------------

> // greater than
< // lesser than
>= // greater than or equals to
<= // lesser than or equals to

==, ===, != и !== — это операторы сравнения на равенство, не путайте != и !== с операторами неравенства, они операторы не-равенства и являются просто отрицательными аналогами соответствующих операторов равенства.

Нечеткое равенство и строгое равенство в JavaScript (== vs ===)

Считается, что разница в == и === заключается в том, что == проверяет равенство значений, а === проверяет равенство значений и типов, автор заявляет, что это неточно, а точная разница

== проверяет равенство с допустимым принуждением и === проверяет на равенство с недопустимым принуждением

Это означает, что когда типы операндов различны, значения не равны в случае === (строгое равенство), но в случае == (нечеткое равенство) значения приводятся к общему типу, а затем значения сравниваются. за равенство.

Алгоритмы для обоих этих операторов можно найти здесь, настоятельно рекомендую прочитать.

Оператор == не является транзитивным, т.е.

// a == b and b == c does not mean a ==c. for example 
new String("a") == "a" // true
"a" == new String("a") //true
new String("a") == new String("a") // false

Это связано с тем, что при сравнении нового строкового объекта с примитивной строкой “a” объект приводится к своему примитивному значению в соответствии с алгоритмом свободного равенства, поэтому результат верен, но при сравнении двух новых строковых объектов сравниваются ссылки на объекты. а не значения, и ссылки обоих этих объектов не совпадают, поэтому сравнение дает false.

Алгоритмы === (строгие равенства) и sameValue, которые используются в Object.is(), различаются между собой.

  • их обработка нулями со знаком, 0 и -0 и +0 равны согласно ===, но не Object.is() и,
  • NaN значений, NaN === NaN ложно, а Object.is(NaN, NaN) верно

Области действия в JavaScript

Вы можете объявить переменную, которая будет принадлежать текущей области действия функции или глобальной области видимости, если она объявлена ​​вне какой-либо функции.

function foo() {
  var a = 100; //the variable a belongs to the scope of function foo
  /*

    function body 

  */
}

var b = 1000; 
//the variable b is outside any function so it belongs to the global scope
var c = a * 100; //Error:: a cannot be accessed outside foo

это область действия в JS, одним из важных понятий является подъем.

Подъем в JavaScript

В приведенном выше примере кода переменная a объявлена ​​в области видимости функции foo, а также объявлена ​​вверху, поэтому она доступна внутри полной области действия функции.

Но, если его объявить не вверху, то и он будет доступен во всей области действия функции foo, т.к.

объявление var перемещается в начало области действия.

Это называется Поднятие.
Код не переупорядочивается или что-то в этом роде, просто кажется, что объявление перемещено в верхнюю часть области, но подробности этого находятся в процесс компиляции, который мы обсудим позже.

Просто объявление перемещается наверх, а не присваивание. Поэтому, если вы попытаетесь использовать переменную a до ее объявления, вы получите значение как undefined, только после ее присвоения вы сможете получить фактическое значение переменной.

Строгий режим в JavaScript

«Строгий режим» — это, по сути, только строгий режим, когда строгий режим включен, правила ужесточаются для определенного поведения, и эти ограничения рассматриваются для обеспечения большей безопасности кода, а также ограничения строгого режима делают ваш код более оптимизируемым движком.

строгий режим может быть применен к любому уровню, будь то весь файл или область действия функции, это определяется тем, где вы поместили прагму строгого режима

"use strict";
// this enforces strict mode

function foo() {
  "use strict";
}
// this way strict mode is enabled for function scopes

Автор рекомендует использовать строгий режим.

Функции в JavaScript

Мы знаем, что такое функции, как они объявляются, вызываются и прочее.

Но одна интересная особенность функций в JavaScript заключается в том, что функции — это просто значения, которые присваиваются переменным, точно так же, как и другие значения (числа, строки и т. д.). Функции можно присваивать переменным, передавать функциям в качестве параметров, возвращать из функций.

Немедленно вызываемые функциональные выражения (IIFE) в JavaScript
Один из способов вызвать функцию — добавить () к имени функции, есть и другой способ

(function foo() {
  /*
    function body
  */
})();

это пример IIFE, существует множество вариантов использования IIFE, они обсуждаются в последующих книгах серии.

Замыкания в JavaScript

Замыкание — очень важная часть языка, оно повсюду, и вы можете использовать его, даже не подозревая об этом.

Закрытие — это, по сути, когда мы можем получить доступ к переменным области видимости функции даже после того, как она завершила выполнение, и память всех ее переменных должна быть очищена.

Замыкания происходят в основном, когда функция возвращает другую функцию, которая использует переменные из области видимости внешней функции, например

function outer() {
  var x = 10;
  return function inner(value) {
    return x + value;
  }
}

var y = outer(); 
// the execution of outer has finished here
// the memory assigned to variable x should be freed
// and we must not be able to access the value of x from here on

y(100);
// because of closures we can access x when we are calling y()
// this call returns 110 because x is accessible to the inner function

Существует так много применений замыканий, что мы обязательно обсудим их в посте второй книги Scopes & Closures. Одним из примеров, обсуждаемых в этой книге, является

function makeAdder(valueToAdd) {
  function add(x) {
    return x + valueToAdd;
  }
  return add;
}

var addOne = makeAdder(1);
var addFive = makeAdder(5);

addOne(2) // returns 3
addFive(2) // returns 7

Попытайтесь понять приведенный выше код, это то, что делает замыкания такими мощными.

Модули в JavaScript

Одним из основных применений замыканий являются модули. Модули помогают создавать функциональные возможности, в которых можно скрыть частные детали реализации, такие как функции и переменные, и предоставить только общедоступный API, доступный извне. например

function App() {
  function somePrivateMethod() {
    // function body
  }

  function somePublicMethod() {
    // function body
  }

  var somePublicVariable = 100;

  var somePrivateVariable = "key";

  var publicApi = {
    somePublicVariable,
    somePublicMethod,
  }

  return publicApi;
}


var appAPI = App(); 
// only public api is exposed to the user
// rest of the implementation details are hidden

appAPI.somePublicMethod() // is accessible

appAPI.somePrivateMethod() // ERROR: is not accessbile so is undefined

thisидентификатор в JavaScript

this — еще одна широко неправильно понимаемая концепция JS. Люди со знанием других языков, таких как Java, могут полагать, что this связано с объектно-ориентированным поведением, но это не так в JavaScript.

this ссылка в функции обычно относится к объекту, который зависит от того, как была вызвана функция. Оно не относится к самой функции.

Существуют различные способы вызова функции, мы кратко обсудим, как значение идентификатора this отличается в этих случаях, это фрагмент кода из книги

function foo() {
  console.log(this.bar);
}

bar = "hello";

var obj1 = {
  bar: "hi",
  foo: foo,
};

var obj2 = {
  bar: "obj2 hi",
};

foo(); 
/* logs hello without strict mode 
  ** without strict mode the this identifier defaults to the global object
  ** in strict mode the this identifier defaults to undefined 
*/

obj1.foo();
// logs hi -> this way of calling sets this identifier to obj1

foo.call(obj2)
// logs obj2 hi -> this way of calling sets this identifier to obj2

new foo();
// logs undefined -> this way of calling sets this identifier to an empty object

это основные правила, связанные с this , им посвящены главы в следующих книгах, мы подробно обсудим их в следующих постах.

Прототипы в JavaScript

Механизм прототипа в JavaScript связан с объектами, когда вы пытаетесь получить доступ к свойству объекта, если это свойство отсутствует в объекте, JS пытается найти другой объект из внутренней ссылки на прототип объекта для поиска этого свойства, это это как запасной вариант.

Это внутреннее связывание прототипов происходит, когда объект создается, пример, указанный в книге,

var obj1 = {
  bar: "bar",
}

var obj2 = Object.create(obj1);

obj2.foo = "foo";

obj2.foo; // "foo"
obj2.bar; // "bar"

// bar does not exist directly in obj2 but is present in obj1
// and obj1 is added as the prototype of obj2 using object.create()
// so JS looks for bar in obj1 and finds "bar"

Это только введение, прототипы подробно обсуждаются в третьей книге this & Object Prototypes.

Полифиллинг и транспиляция в JavaScript

Время от времени выпускаются новые версии языка с новыми функциями, но поддержка этих функций не обязательно доступна сразу, а иногда даже позже.

Чтобы решить эту проблему, у нас есть полифилл, он работает путем добавления фрагмента кода, который эквивалентен поведению новой функции, например, в книге показано, что Number.isNaN() является новой функцией и может не работать в старых браузерах, поэтому для ее полифилла мы добавляем этот кусок кода

if (!Number.isNaN) {
  Number.isNaN = function isNaN(x) {
    return x !== x;
  };
}

Он проверяет, доступна ли функция, если нет, то добавляет ее.

Полифиллинг работает с новыми функциями, но в случае изменений синтаксиса, которые приходят с новыми обновлениями языка, полифилл нельзя использовать, в этом случае используется транспиляция кода.

Преобразование нового синтаксического кода в старый синтаксический код является транспилированием, транспиляторы используются для транспиляции кода, babel — широко известный и используемый транспилятор.

Некоторые интересные вещи об использовании JavaScript

Как мы знаем, JS в основном написан для взаимодействия с такими средами, как браузер. Большая часть кода, который мы пишем, не контролируется JavaScript, потому что, когда мы используем такие вещи, как document.getElementById(), кажется, что document — это объект JS, но это не так, это глобальная переменная, которая является специальным объектом, который называется host objects.

Функция getElementById, которую мы вызываем, также выглядит как функция JS, но это всего лишь интерфейс, предоставляемый нам DOM из браузера. В некоторых браузерах это может быть реализовано в самом JS, но чаще всего это реализовано в таких языках, как C/C++ и т. д.

console.log() и alert тоже не JS.

Что эта серия сулит нам, разработчикам?

Эта первая книга была введением в язык, все эти концепции подробно объясняются в следующих книгах, список книг в YDKJS:

  • Области действия и замыкания. Эта книга призвана прояснить основы областей действия и замыканий в JS, которые имеют решающее значение для понимания JS. Книга начинается с разоблачения неправильного представления о том, что JS интерпретируется, а не интерпретируется, и поэтому мы углубляемся в то, как компилятор читает наш код и работает с объявлениями функций и переменных, затем книга переходит к пониманию лексической области видимости, а затем, наконец, к замыканиям и некоторым варианты использования, такие как шаблон модуля, который мы обсуждали немного ранее.
  • this & Object Prototypes — рассказывает о ключевом слове this, которое мы обсуждали ранее, и о четырех правилах, определяющих его значение в вызове функции, затем он переходит к обсуждению прототипного наследования в JS и что это не то же самое, что классы и наследование, а скорее делегирование поведения, автор утверждает, что делегирование поведения является лучшим шаблоном проектирования, чем классы и наследование.
  • Типы и грамматика — в этой книге рассказывается о принуждении, обсуждается, как легко и важно его понять, а не игнорируется и избегается принуждение, и клеймит его как изъян языка.
  • Асинхронность и производительность. В этой книге обсуждается асинхронное программирование в JS, разбираются параллельные, асинхронные и параллельные функции, обсуждаются обратные вызовы как метод асинхронного программирования, затем обсуждаются связанные с ним проблемы, а затем обсуждаются решения этих проблем. промисами и генераторами, а также охватывает веб-работников и SIMD. Эта книга предназначена для того, чтобы дать вам инструменты и навыки для написания разумного и производительного кода JS.
  • ES6 & Beyond. В этой книге говорится, что JS постоянно развивается, и поэтому основное внимание уделяется новым функциям, добавленным в язык в ES6.

Это первая книга из серии. Это было хорошее чтение и обучение для меня, я надеюсь, что это было полезно. Надеюсь не отставать, прочитать всю серию и познакомиться с JS.