Автор оригинала: FreeCodeCamp Community Member.
Что нужно знать, чтобы быть отличным разработчиком JavaScript
Ты уже бывал там раньше? Где JavaScript просто не работает. Где функции, которые вы пишете, не делаете то, что вы ожидаете их? Где это
просто не имеет смысла? Что такое это
? Это это
Отказ
У меня есть. Итак, я написал эту статью. Он охватывает все от закрытия и классов до предметов и подъема.
Это помогло мне стать лучшим разработчиком. Я надеюсь, что это вам тоже поможет.
Модель данных
Типы
Придерживайтесь меня. Я делаю это, потому что есть два не очень известных типа, я хочу, чтобы вы знали: символы и цифры.
Также разница между неопределенными и нулевыми ускользающими многими.
Числа
Все номера в JS – это «двойная точность 64-битного формата IEEE 754 значений». Обычно известны как поплавки, что означает, что нет концепции целого числа. Ваши целые числа хранятся как поплавки.
Для преобразования строк на цифры: используйте Parсент ('123', 10)
Отказ Второй аргумент является основой. Итак, при работе с двоичным, вы могли бы сделать:
> parseInt('101',2) 5
Точно так же Parsefloat («Номер»)
существует для количества плавающих точек. База здесь всегда 10.
Символы
Единственная цель этого типа данных состоит в том, чтобы идентифицировать свойства объекта. Протокол итерации и Regex являются наиболее популярными примерами, использующими символы. Мы рассмотрим протокол итерации в следующей части!
Вы можете создать один через Символ ()
Отказ Каждый звонок генерирует новый символ. Таким образом,
console.log(Symbol(42) === Symbol(42)) // false
Символы могут сохраняться через файлы в JavaScript. В этом смысле они отличаются от глобальных переменных.
Существует глобальный реестр символов, который хранит все встречаемые символы. Чтобы добавить символ в реестр, используйте Символ. Для ()
и получить использование символа Symbol.keyforyfor ()
Отказ
Больше информации о символах см. здесь Отказ
Неопределенный и нулевой
Почему различие между неопределенным и нулевым?
По соглашению NULL указывает на преднамеренное несуществующее значение. И undefined – это неинициализированное значение.
Например, скажем, у вас есть поле, которое хранит идентификатор, если он существует. В этом случае вместо использования волшебного значения, такого как «Not_exists», вы можете использовать NULL. Если он должен существовать, но сейчас нет прямо сейчас, вы можете показать, что через undefined.
Переменные и облаки
До ES2015
var
был единственным способом определить переменные.
Далее у нас были только два облагания: глобальный и Функция объем. Переменные, объявленные внутри функции, становятся местными для этой функции. Что-нибудь за пределами объема функций не может получить доступ к ним.
Таким образом, они имели функциональные масштабы.
После ES2015
ES2015 представила два новых способа определения переменных:
позволять
конститут
С ними пришла концепция Блок объем. Блок – это все между двумя фигурными брекетами {..}
ES2015 – это обратно совместим, поэтому вы все еще можете использовать var, хотя их использование обескуражено.
var x = 1; { var x = 2; } console.log(x) // OUTPUT: 2, as block doesn't mean anything to var. let x = 1; { let x = 2; } console.log(x) // OUTPUT: 1
Переменная подъемность
JavaScript имеет своеобразную идею с var
называется подъемником.
function something() { console.log(name); let name = 'neil'; console.log(name); }
Можете ли вы угадать, что будет выше?
Я говорю Собственный ресурс
: Мы используем имя переменной до определенного. Это имеет смысл, вот что происходит.
Однако, если бы я использовал var
вместо Пусть
Я бы не получил ошибку.
function something() { console.log(name); // OUTPUT: undefined var name = 'neil'; console.log(name); // OUTPUT: neil }
Что происходит за кулисами?
function something() { var name; // variable hoisting console.log(name); // OUTPUT: undefined name = 'neil'; console.log(name); // OUTPUT: neil }
Это еще одна причина, по которой использование var
обескуражен. Это может привести к интересным ошибкам.
Короткие замыкания логика: && и ||
С JavaScript что-то своеобразное происходит с логическими операциями. (А в Python тоже.)
То, что позволяет вам делать тайные вещи, как это:
// o is an object var name = o && o.name;
Как вы думаете, что Имя
является? Если объект, o
это нулевой или неопределенный, Имя
это нулевой или неопределенный.
Если o
определяется, но O.Name
не определен, Имя
не определен.
Если o
определяется, O.Name
определяется, то name.name
Отказ
Мы использовали логический логический оператор правильно? Как это возможно тогда? Ответ короткое замыкание и правдивость.
Правдивость
Значение – это правда, если он оценивает правду в логическом контексте. Все значения являются правдой, за исключением следующих фальсифицированных значений:
ложный
0
""
значение NULL
неопределенный
Нан
Примечание: что означает, {}
и []
Пвердые!
Обычный трюк, чтобы преобразовать что-то в свою правдовую ценность: !
!
Преобразуется не – ложное значение – и !
снова преобразует его обратно в true/false.
Короткое замыкание
Идея – это логические операторы возвращают окончательное значение, которое делает оператор TRUE или FALSE, а не правильно ли утверждение или ложное. Как мы видели выше, чтобы преобразовать его в правдовую ценность, вы можете использовать !
Отказ
Короткое замыкание происходит, когда логическое выражение не оценивается полностью. Например,
значение NULL && …
Неважно, что ...
является. null
является ложностью, поэтому это выражение вернется null
Отказ
Тот же случай с []
… Отказ
[] это правда, так что это выражение вернется
[] , независимо от того, что
…
Объекты
Объект в JavaScript – это коллекция пар ценностей имени. Если вы идете от Как больше не бояться питона , не путайте объект Python с объектом JavaScript.
Ближайшая эквивалентность для JavaScript Объект
Питон Диктовать
Отказ
Для типов, доступных в объекте, Имя: строка
или Символ
Значение: что угодно.
Массивы
являются специальным типом объекта. У них есть волшебное свойство: длина (и разная цепь прототипа. См. Ниже.) Длина массива – один раз, чем самый высокий индекс. Это смежно, что означает, что вы можете сделать в фанкные вещи с ним (не рекомендуется):
const funkyArray = []; funkyArray['0'] = 'abcd'; funkyArray['length'] = 3 > console.log(funkyArray); (3) ["abcd", empty × 2] > funkyArray[4] = 'x'; > console.log(funkyArray); (5) ["abcd", empty × 3, "x"]
Обратите внимание на использование номеров и строк в качестве индексов массива. Числа работают, потому что объекты неявно звонят TOSTRING ()
на имя.
Итализация над массивами и объектами, используя такие конструкции, как для ... из
, для ... в
и foreach
Это то, что я уйду на следующую часть. (Плюс интересный ошибчик при использовании объектов в качестве карт в JavaScript!)
Глобальный объект
Глобальный объект – это объект Это всегда существует в глобальном масштабе. В JavaScript всегда определен глобальный объект. В веб-браузере, когда скрипты создают глобальные переменные, они созданы как члены глобального объекта [ 1 . Интерфейс глобального объекта зависит от контекста выполнения, в котором работает скрипт. Например:
- В веб-браузере любой код, который скрипт специально не запускается в качестве фоновой задачи, имеет окно в качестве глобального объекта. Это подавляющее большинство JavaScript Code в Интернете.
- Код, работающий у работника, имеет рабочий объект рабочего процессота в качестве его глобального объекта.
- Сценарии, работающие под Node.js, имеют объект под названием Global в качестве глобального объекта. [ 2 Несомненно
Функции
В JavaScript функции являются объектами первого класса. Они могут иметь свойства и методы, такие как любые другие объекты. Они могут быть переданы другим функциям в качестве параметров (мета-рекурсия!). Способ функций отличается от объектов, заключается в том, что они вызываются.
Все функции расширяют Функция объект. Этот объект не имеет свойств или методов заранее определенных, но наследует некоторые из Функция. Прототип
Отказ (Это станет ясным в разделе прототипа ниже). Далее это Функция
Объект является конструктором для функций. Вы можете создавать функции не менее 4 способов:
function functionDeclaration() {}; var anonymousFunctionExpression = function() {}; var namedFunctionExpression = function named() {}; var arrowFunctionExpression = () => {}; var constructorFunction = new Function(...args, functionBody); // functionBody is a string
Заявление об возврате может в любое время возвращать значение, завершающее функцию. JavaScript возвращает undefined, если оно не видит оператора возврата (или пустое возвращение без значения).
Все аргументы, определенные для функции, идут в аргументах var. Значение по умолчанию для всех аргументов – undefined
Отказ
Вы когда-нибудь видели три точки в JavaScript раньше? ...
Отказ Как тот, который я использовал выше в Конструкторфункция
? Они очаровали мой разум в первый раз, когда я увидел их. Они являются частью синтаксиса в JavaScript. Это не псевдокод (как я впервые подумал).
Они Отдых
и Распространение
Синтаксис параметра.
Являются противоположности друг от друга. Распространение
распространяет аргументы, Отдых
возвращает их вместе.
Вот пример: оправдывайте плохо разработанную функцию – что не нужны аргументы, которые нужно назвать – но я делаю точку.
const average = function( val1, val2, val3, ...otherValues) { // rest console.log(otherValues); let sum = 0; for (let i = 0; i < arguments.length; i++) { sum += arguments[i]; } return sum / arguments.length; } let values = [1, 2, 3, 4, 5, 6] const averageValue = average(...values); // spread
Что тут происходит? Другие значения
Использует синтаксис остального, чтобы собрать бесконечное количество аргументов, переданных в среднем. console.log ()
будет печатать [4, 5, 6]
выше.
Значения
Используется синтаксис спреда, чтобы преобразовать массив в один аргументы. Это работает так, что за кулисами ниже эквивалентно вышеуказанному.
const averageValue = average(1,2,3,4,5,6)
Другое, что следует отметить, что значения аргументов по умолчанию оцениваются каждый раз, когда вызывается функция, в отличие от Python, где это происходит только один раз.
Существует 3 интересных прототипа функций, доступных для функционирования объектов. Это Применить ()
, Bind ()
и Позвоните ()
Отказ A, B, C JavaScript.
С появлением распространения и синтаксиса отдыха Применить ()
и Позвоните ()
не разные больше нет.
Применить ()
вызывает функцию с массивом args; Позвоните ()
вызывает функцию с отдельными значениями.
Прохладный бит, они позволяют вам вызвать функцию с пользовательским это
объект.
Мы поговорим больше о Применить ()
и Bind ()
Как только мы покрываем это
объект.
Анонимные и внутренние функции
const avg = function () { let sum = 0; for (let i = 0, argLength = arguments.length; i < argLength; i++) { // arguments variable is an array containing all args passed to the function. sum += arguments[i]; } return sum / arguments.length; // argLength isn't available here };
Выражения Функция AVG ()
и var ()
семантически эквивалентны.
Тем не менее, существует различие между именем функции (здесь Anonymous – поэтому не существует), а вариабельная функция назначена.
Имя функции не может быть изменено, а вариабельная функция назначена для переназначения. Имя функции можно использовать только в теле функции. Попытка использовать его вне тела функции приводит к ошибке (или не определено, если имя функции ранее было объявлено через оператор var).
Эта идея прошедших функций в качестве переменных порождает огромную мощность. Например, вы можете скрыть локальные переменные:
var a = 1; var b = 2; (function() { var b = 3; // hidden local variable a += b; })(); a; // 4 b; // 2
Вышеупомянутое выражение называется IIFE (немедленно вызываемая функцией выражения) – где вы создаете функцию и сразу же вызовите ее.
Далее мы можем гнездить функционировать внутри друг друга! Они называются Внутренние функции Отказ Важно помнить: внутренние функции имеют доступ к переменным, определенным в родительских функциях, но не наоборот. Это прямой результат закрытия, которые мы скоро покроем.
Это позволяет создавать такие функции, как:
let joiner = function(separator) { // The outer function defines separator return function(left, right) { return left + " " + separator + " " + right; // The inner function has access to separator } // This exposes the inner function to the outside world } let and = joiner("and"); and("red", "green"); // There's no way to change the separator for AND now; except by reassigning the function variable. // red and green const or = joiner("or"); // There's no way to change the separator for OR now. or("black", "white"); // black or white
Функциональный подъемник
Хорошо, вы можете запутаться в том, какова разница между условиями. Я был.
function declaredFunction() { // this is the function declaration // what comes here is the function definition } let functionExpression = function() { // this is a function expression // what comes here is the function definition }
Классы и цепь прототипа
JavaScript использует функции в качестве классов. Недавно введенное классовое заявление является синтаксическим сахаром над функциями.
Поскольку все данные в JavaScript это Объект
Имеет смысл, что наши функции – это конструктор класса – вернет Объект
Отказ
Таким образом, учитывая все основы, мы знаем о функциях и объектах, мы можем сделать что-то вроде этого, чтобы создать класс для, скажем, (Думает действительно трудно выяснить нетривиальный, полезный и относительный пример …) … … .. Отказ Tweet Interface! Это звучит забавно.
Представьте, что вы строите свою собственную интерфейс, чтобы показать твиты, разговаривая с API Twitter, чтобы получить данные для твитов.
function Tweet(id, username, content, parent = null) { return { id, // Javascript implicitly converts this into id: id username, content, getUrl: function() { return 'https://twitter.com/' + this.username + '/' + this.id; }, isComment: function() { return parent !== null; } }; } var t = Tweet(1, '@neilkakkar', 'How not to be afraid of JS anymore'); // Remember, we can fill any number of args // the rest are undefined or default // All args are in the arguments variable t.getUrl(); // "https://twitter.com/@neilkakkar/1" t.isComment(); // "false"
это Свидетельство ключевых слов текущий объект. Используя точечную обозначение, это становится объектом, на котором была применена точка. В противном случае это глобальный объект.
Примечание от MDN:
Это (каламбур) является частой причиной ошибок. Например:
const t = Tweet(1, '@neilkakkar', 'How not to be afraid of JS anymore'); const urlFetcher = t.getUrl; // assigning the function urlFetcher(); // https://twitter.com/undefined/undefined
Когда мы называем URLFetcher ()
в одиночку, без использования t.geturl ()
, это
связан с глобальным объектом. Так как нет глобальных переменных, называемых Имя пользователя
или ID
Мы получаем undefined
для каждого.
Мы можем воспользоваться это
Ключевое слово для улучшения нашей функции Tweet. Идея состоит в том, что вместо создания объекта и возврата, мы ожидаем, что новый объект (ссылка на это
) и измените его свойства.
function Tweet(id, username, content, parent = null) { this.id = id; this.username = username; this.content = content; this.getUrl = function() { return 'https://twitter.com/' + this.username + '/' + this.id; }; this.isComment = function() { return parent !== null; } }; } var t = new Tweet(1, '@neilkakkar', 'How not to be afraid of JS anymore');
Новый Ключевое слово создает совершенно новый пустой объект, а затем вызывает указанную функцию, с помощью это
установить на новый объект. Наша модифицированная функция не возвращает значение, но просто модифицирует это
объект. Новый
также возвращает это
Объект, как только функция вызывается на нем. Это то, что мы хотели. Новый
Также есть ли дополнительные вещи, которые мы хотим – как создать цепочку прототипа – но мы получим это немного.
Такие функции, которые предназначены для вызова Новый
, называются Конструктор Функции Отказ По соглашению, эти функции капитализируются (как напоминание называть их с Новым
).
Так как мы получаем новый объект каждый раз, когда мы называем Tweet
У нас есть две функциональные объекты ( Geturl
и Reachment
) Создано каждый раз, когда мы называем Tweet
Отказ Лучший способ – написать эти функции за пределами объема конструктора – и пройти ссылку.
Если вы идете с фона OOP, даже это может казаться достаточно хорошими. Вы не хотите, чтобы эта функция была использована где угодно, но для этого Tweet
объект. Вы не хотите загрязнять свой глобальный список функций. Это где приходит «наследство» JavaScript.
Прототип
Tweet.Prototype
Объект, разделяемый всеми случаями Tweet
Отказ Он формирует часть цепи поиска (имеет особое имя, «цепь прототипов»): в любое время доступа к недвижимости Tweet
Это не установлено, JavaScript проверит Tweet.Prototype
чтобы увидеть, существует ли эта собственность там.
В результате все назначено для Tweet.Prototype
становится доступным для всех экземпляров этого конструктора через это
объект.
Это невероятно мощный инструмент. JavaScript позволяет вам изменять прототип в любое время в вашей программе, что означает, что вы можете добавлять дополнительные методы к существующим объектам во время выполнения (без необходимости снова вызывать конструктора).
var t = new Tweet(1, '@neilkakkar', 'How not to be afraid of JS anymore'); t.getComments(); // TypeError on line 1: t.getComments is not a function Tweet.prototype.getComments = function() { // example API call to Twitter API - let's say it exists as the twitterService object return twitterService.getComments(this.id); }; t.getComments(); // "[ 'This is an amazing article, thank you!' , 'I love it' ]" // fictional comments
Функция. Прототип против __proto__
Вы, наверное, видел оба использования взаимосвязанно. Они не одинаковы. Давайте рассмотрим это.
Функция. Прототип
это конструктор для __proto__
Отказ
__proto__
является фактическим объектом прототипа, доступного на объектах.
Таким образом, Функция. Прототип
доступно только для конструктора функций. Вы не можете получить доступ к прототипу для твита, как t.prototype
вам придется использовать т .__ Proto__
Отказ
Но установить прототип, вы бы использовали Tweet.prototype.getComments ()
Как в приведенном выше примере.
Осведомление того, что мы сделали с функциями и классами
- Классы – это функции. Мы начали с функции, которая создала новый объект (
return {...}
– используя объектный литеративный синтаксис), затем добавляя свойства к нему (данные класса) и, наконец, возвращая его. - Затем приходят функции конструктора. Эти предполагают, что есть данный пустой объект (инициализирован через
New
) и просто добавить его свойства. - Затем наступает цепочка прототипа, для методов, которые будут использоваться всеми объектами
учебный класс
За кулисами, вот как все работает при использовании Класс
ключевое слово.
Новое ключевое слово и применять
Теперь мы можем исследовать, что происходит за кулисами с Новый
и Revisit Применить ()
из функционального прототипа. Мы уже видели Bind ()
Отказ
Функция Новый
Создано создать объект, пропустите его в функцию конструктора (где этот объект доступен как это
) и настроить цепь прототипа.
Применить ()
принимает объект ( это
значение) и массив аргументов, которые будут вызывать этот объект.
Положить эти два вместе, мы получаем тривиальную реализацию новых.
function newNew(constructorFunction, ...args) { const thisObject = {}; // create object using object literal syntax constructorFunction.apply(thisObject, args); // calls constructorFunction with this set to thisObject and with given args // setting up prototype chain is tricky. Need a new prototype for constructorFunction // not the Function constructor prototype return thisObject; }
Закрытие
Помните столярную функцию?
let joiner = function(separator) { // The outer function defines separator return function(left, right) { return left + " " + separator + " " + right; // The inner function has access to separator } // This exposes the inner function to the outside world } let and = joiner("and"); and("red", "green"); // There's no way to change the separator for AND now; except by reassigning the function variable. // red and green const or = joiner("or"); // There's no way to change the separator for OR now. or("black", "white"); // black or white
Функция, определенная внутри другой функции, имеет доступ к переменным внешней функции. Как только возвращается внешняя функция, здравый смысл будет диктовать, что его локальные переменные больше не существуют.
Но они существуют – в противном случае столярные функции не будут работать. Более того, есть два разных «копии» Столяр ()
локальные переменные – один, в котором разделитель
это и
а другой, где разделитель
это или
Отказ Как это работает?
Объект масштаба
Всякий раз, когда JavaScript выполняет функцию, она создает объект «Scope» для удержания локальных переменных, созданных в этой функции. Объект SCOPE инициализируется переменными, переданными в качестве параметров функций. Это похоже на глобальный объект – как новые переменные «отображаются», они добавляются в объект объема.
Две ключевые моменты:
- Совершенно новый объект Scope создан каждый раз, когда функция начинает выполнять
- В отличие от глобального объекта, эти объекты объема не могут быть напрямую доступ к вашему коду JavaScript. Не существует механизма для итерации по свойствам объекта текущего объема.
Так когда Столяр ()
вызывается, объект объема создается с одним свойством: разделитель
, который аргумент передан Столяр ()
Отказ Столяр ()
Затем возвращает созданную функцию.
Обычно сборщик мусора JavaScript будет очищать объект Scope, созданный для Столяр ()
На данный момент, но возвращенная функция поддерживает ссылку обратно на этот объект объема. В результате объект объема не будет собираться мусором, пока больше нет ссылок на объект функции, который Столяр ()
вернулся.
Объекты олечения формируют цепь, называемую цепью области, аналогичную цепью прототипа.
Таким образом, вы создаете закрытие, когда вы создаете функцию внутри другой функции.
Представление
Чтобы закончить этот раздел, давайте немного поговорим о производительности. Оптимизировать производительность, избавиться от замыканий не нужна. Помните, что эта ссылочная проживание до тех пор, пока не требуется объект масштаба, содержащий все локальные переменные и функционирующие аргументы.
function f(i) { var o = { }; // Some large object var a = [ ]; // Some large array // `a` and `o` are local variables and thus will get added to the closure object. //... //... // some use case for a and o var c = [ 1, 2, 3 ].filter(item => a.indexOf(item) > -1 || o[item]); a = undefined; // Clean up before closure o = undefined; // Clean up before closure return function () { // closure created return ++i; // we didn't need anything except i for this function, // so makes sense to delete everything else from the closure. }; }
Модель исполнения
Как работает JavaScript?
Этот GIF показывает различные компоненты и как они взаимодействуют вместе. Давайте пройдемся через них.
Стек вызовов
Каждый вызов функции – это кадр на стеке.
Этот стек вызовов представляет собой стопку функционирования вызовов для выполнения в порядке. (Вы видите, почему это называется стек?)
Рама содержит функциональные аргументы и локальные переменные. Именно здесь определяется объект масштаба и, следовательно, закрытие!
Функции выскочины из стека, когда они возвращаются.
Каждый скрипт начинается с Главная ()
В стеке, как функция, содержащая все другие функции в скрипте.
Куча
Каждый объект, который вы создаете, нуждается в месте в памяти, чтобы жить. Это место – это куча: большая неструктурированная область памяти.
Если вы идете с земли C ++, куча там, где все происходит, когда построено с использованием Новый
в C ++.
Веб-АПИ и события
Веб-API – это функции низкого уровня, присутствующие в среде выполнения JavaScript для взаимодействия с ОС. Они реализуются браузером/хостом. Для бывшего: Setimeout ()
Отказ
Они называются из стека и начинают обработку. Функция возвращается на данный момент (тем самым появляется кадр стека). Это то, что дает JavaScript асинхронную характеристику. Почти все его основные API не блокируют.
Посмотрите на GIF выше – и этот бит станет яснее.
Эти API генерируют сообщение. Это может быть вызов API для извлекать
Данные, в этом случае сообщение – это данные. Это может быть Setimeout ()
, где сообщение пусто. Это может быть событие на кнопке DOM, как OnClick
, где сообщение – это информация, хранящаяся в кнопке.
APIS отправляют эти сообщения в очередь обратного вызова. У них есть функция обратного вызова, которая прикреплена к сообщению. Этот обратный вызов получен из стека вызовов (что-то, что мы предоставляем при вызове API).
Очередь обратного вызова
Это очередь, содержащая все задачи, которые закончили обработку. Он имеет очередь сообщений с функциями обратного вызова для каждого сообщения.
Для обработки сообщения функция обратного вызова называется с сообщением в качестве ввода – но очередь не может сделать это, это просто очередь сообщений. Эта обработка достигается через петлю события.
Веселый факт : Эта очередь обычно известна как очередь макрота. Там тоже небольшая очередь микрозазки, скрывающаяся тоже. Не многие люди не знают об этом – но это входит в игру при дело с обещаниями. История для будущей статьи, возможно,? (Вау, JS огромный, не так ли?)
Контур событий
Чтобы вызвать обратные вызовы в очереди обратного вызова, нам нужно вернуть их на стек вызовов. Это единственный способ, которым называется функция.
Структура события обрабатывает этот бит. Это управляющая петля, которая проверяет, если стек вызовов пуст на каждом петле.
После того, как стек вызова пуст, цикл события принимает первый элемент из очереди обратного вызова и передает обратный вызов на стек вызова.
Заканчивать
В контуре события каждое сообщение работает до завершения. Это означает, что в стек вызова не будет добавлено новое сообщение, пока текущее сообщение выполняется.
Опораемая модель выполнения
Хорошо, мы много охватываем здесь. Некоторый код следует, но до этого я хочу убедиться, что все понятно.
- Как только вы выполните скрипт,
Главная ()
Функция добавляется в стек вызова. - В качестве функций вызываются из скрипта, они добавляются в стек вызова. Выскочил при возвращении.
- Объекты охвата добавляются функциями в стек вызова.
- Некоторые функции также могут иметь компонент обработки – который обрабатывается API. Эти API возвращают сообщение и обратный вызов.
- Сообщения добавляются к очереди обратного вызова.
- Структура событий передает сообщения из очереди обратного вызова в стек вызова только тогда, когда стек вызовов пуст (I.e
Main ()
- Каждое сообщение работает до завершения (прямое следствие новых сообщений, добавленных только тогда, когда стек пуст)
С этой переутомлением давайте нанесемся. Setimeate (обратный вызов, т)
Это функция (API), как определено выше, что делает обратный вызов и добавляет сообщение в очередь обратного вызова после T
секунды.
Итак, какой был бы порядок печати ниже?
console.log('1'); setTimeout( () => console.log(2), 0) // t = 0; console.log('3');
…
..
.
Если вы догадались 1 2 3
Давайте пройдемся через пример.
Первоначально у нас есть Главная ()
на стек вызова. Затем мы продвигаем скрипт.
Мы видим console.log (1)
– это попадает в стек вызова, отпечатки 1
и выскочит.
Мы видим Setimeout ()
– Это происходит в стеке вызовов, передает веб-API и выскочит.
В то же время, поскольку время ожидания было в течение 0 секунд, обратный вызов передается в очередь обратного вызова.
Мы видим console.log (3)
– это попадает в стек вызова, отпечатки 3
и выскочит.
Сценарий заканчивается, так что Главная ()
выскочил.
Теперь стек вызова пуст, поэтому Setimeout ()
Обратный вызов передается в стек вызова.
То есть у нас есть () => Console.log
(2) в стеке вызовов. Это называется с t он и
Ull сообщение.
Следовательно, заказ – 1 3 2
Отказ
Это нулевая задержка Gotcha – удобная идея напоминать себе о том, как работает петли событий.
Это похоже на хорошее место, чтобы остановиться сейчас. Я надеюсь, что эта статья помогла вам начать получать лучшее понимание JavaScript!:)
Использованная литература:
[1] Реинтродукция для JavaScript [2] MDN Общие документы
Вот часть 2 в моем блоге.
Другие истории в этой серии:
Как больше не бояться Гит
Как больше не бояться
Как больше не бояться Python
Читать дальше моих статей на neilkakkar.com Отказ