Одна из самых фундаментальных моделей почти любого языка — хранить значения в переменных и извлекать или изменять эти значения позже. Возможность сохранять и извлекать значения в переменных дает состояние программы. Это приводит к двум вопросам: где хранятся эти переменные? Как программа находит их, когда они нужны? Чтобы ответить на эти вопросы, требуется четко определенный набор правил, определяющих, как хранятся переменные и как их найти. Мы называем этот набор правил: область действия.
LHS и RHS Запросы
Прежде чем говорить об области видимости в javascript, я подумал, что было бы полезно сначала понять запросы LHS и RHS.
Несмотря на то чтоjavascript
Он считается интерпретируемым/динамическим языком, но на самом деле это компилируемый язык. Как правило, требуется периодjavascript
кода, есть две важные вещи:JS-движокипереводчик. Первая похожа на роль менеджера, отвечающего за планирование различных ресурсов, необходимых для работы всей программы; вторая является лишь частью первой, отвечающей заjavascript
Исходный код компилируется в машинные инструкции, которые машина может распознать, а затем передается движку для запуска.
компилировать
существуетjavascript
, часть исходного кода, вероятно, пройдет следующие три шага перед выполнением, что также известно каккомпилировать:
-
сегментация слов / лексический анализ: компилятор сначала разбивает последовательность символов на значимые сегменты (для языка), называемые токенами, например.
var a = 2;
. Эта программа, вероятно, будет разбита на следующий токен:var
,a
,=
,2
,и;
. -
разбор / разбор: компилятор преобразует
token
поток (массив) в «абстрактное синтаксическое дерево» (AST —— Abstract Syntax Tree
), который представляет собой грамматическую структуру программы. - генерация кода: компилятор преобразует абстрактное синтаксическое дерево, сгенерированное на предыдущем шаге, в машинные инструкции, ожидая выполнения движка.
воплощать в жизнь
Компилятор работает как тигр и генерирует кучу машинных инструкций, движок JS с радостью получает эту кучу инструкций и начинает их выполнять О чем мы хотим поговорить на данный моментLHS
иRHS
появившийся.
LHS (Left-hand Side)
иRHS (Right-hand Side)
, — это два способа для движка JS манипулировать переменными на этапе выполнения кода. Разница между ними заключается в том, что целью запроса переменных являетсяприсвоение переменнойвсе ещеЗапрос.
LHS
Можно понимать как переменную в операторе присваивания(=)
слева от , напр.a = 1
, текущая переменная пары двигателейa
Цель поиска -присвоение переменной. В этом случае движку не нужна переменнаяa
каково исходное значение, просто введите значение1
назначатьa
Переменная.
RHS
Можно понимать как переменную в операторе присваивания(=)
справа, например:console.log(a)
, где движок связывает переменнуюa
Цель поиска состоит в том, чтобыЗапрос, нужно найти переменнуюa
Каково соответствующее фактическое значение, прежде чем его можно будет распечатать.
Взгляните на следующий код:
var a = 2; // LHS 查询
Когда этот код запускается, движок выполняетLHS
узнать, найтиa
, и введите новое значение2
назначить его. Посмотрите на следующий абзац:
function foo(a) { // LHS 查询
console.log( a ); // RHS 查询
}
foo( 2 ); // RHS 查询
Чтобы выполнить его, движок JS выполняет обаLHS
запрос выполнен сноваRHS
запрос, но здесьLHS
Сложнее найти.
Короче говоря, если движок хочет получить/назначить переменные, он не может обойтись безLHS
иRHS
, но эти две операции — всего лишь средства, где взять переменные — это ключ.LHS
иRHS
Место для получения переменнойсфера.
что такое объем
Проще говоря,сфераОтносится к области в программе, где определены переменные, которая определяет права доступа исполняемого в данный момент кода к переменным.
javascript
В большинстве случаев существует только два типа прицела:
- глобальная область: глобальная область — это самая внешняя область действия программы, которая существует всегда.
- объем функции: область действия функции создается только тогда, когда функция определена и содержится в области родительской функции/глобальной области.
Из-за ограничения области каждый независимый блок исполняемого кода может получить доступ только к переменным в своей области и внешней области и не может получить доступ к переменным во внутренней области.
/* 全局作用域开始 */
var a = 1;
function func () { /* func 函数作用域开始 */
var a = 2;
console.log(a);
} /* func 函数作用域结束 */
func(); // => 2
console.log(a); // => 1
/* 全局作用域结束 */
цепочка прицелов
В приведенной выше демонстрации кода исполняемый блок кода может находить переменные в своей области.Если целевая переменная не может быть найдена в своей области, может ли программа работать нормально? Взгляните на следующий код:
function foo(a) {
var b = a * 2;
function bar(c) {
console.log( a, b, c );
}
bar(b * 3);
}
foo(2); // 2 4 12
Объединив предыдущие знания, мы знаем, что вbar
Внутри функции это будет сделано три разаRHS
запрос для полученияa
b
c
значения трех переменных.bar
Только переменные во внутренней области могут быть полученыc
значение ,a
иb
все снаружиfoo
полученный из области действия функции.
Когда исполняемый код получает доступ к переменной, он сначала будет искать в локальной области, и если целевая переменная будет найдена, он вернется, в противном случае он перейдет в родительскую область для продолжения поиска... до тех пор, пока не будет найдена глобальная область . Мы называем этот вложенный механизм областей действия цепочкой областей действия.
Как показано на рисунке, приведенный выше код имеет в общей сложности три уровня вложенности области видимости, а именно:
- глобальная область
-
foo
сфера -
bar
сфера
Обратите внимание, что параметры функции также находятся в области действия функции.
лексический охват
Теперь, когда мы понимаем концепцию области видимости и цепочки областей видимости, давайте рассмотрим лексическую область видимости.
лексический охват(Lexical Scopes
)Даjavascript
Тип области, используемый в ,лексический охваттакже называемыйстатическая область, в отличие отдинамическая область. Такjavascript
в использованиилексический охватидинамическая областьВ чем разница? Посмотрите на следующий код:
var value = 1;
function foo() {
console.log(value);
}
function bar() {
var value = 2;
foo();
}
bar();
// 结果是 ???
В приведенном выше коде есть три области видимости:
- глобальная область
-
foo
объем функций -
bar
объем функций
Это легко понять до этого момента, ноfoo
получить доступ к переменной, которая не находится в локальной области видимостиvalue
. Согласно тому, что было сказано ранее, двигатель должен пройти, чтобы получить эту переменную.foo
запрос области верхнего уровня, затемfoo
Какова верхняя область ? этокогда звонятв области бара? все еще этокогда определеноВ глобальном масштабе?
Ключевой вопросjavascript
Тип области --Лексический объем.
Лексическая область видимости означает, что когда функция определена, ее область видимости определена, и она не имеет ничего общего с тем, где она выполняется, поэтому лексическая область видимости также называется «статической областью видимости».
Если это тип динамической области, то результат выполнения приведенного выше кода должен бытьbar
в области2
. Может быть, вам интересно, какой язык является динамической областью?bash
Это динамическая сфера, и заинтересованные друзья могут узнать об этом.
область действия блока
Что такое область действия блока? Проще говоря, фигурные скобки{...}
Область представляет собой блочную область.
Многие языки изначально поддерживают область видимости на уровне блоков. Выше мы сказали,javascript
В большинстве случаев существует только два типа прицела:глобальная областьиобъем функции,Такjavascript
Есть ли область действия блока? Взгляните на следующий код:
if (true) {
var a = 1;
}
console.log(a); // 结果???
После запуска вы обнаружите, что результат по-прежнему1
, переменная, определенная и назначенная в фигурных скобках, стала глобальной. Достаточно сказать, чтоjavascript
Он изначально не поддерживает область на уровне блоков, по крайней мере, создатели не учли область на уровне блоков, когда создавали этот язык... (Выйди и возьми на себя вину!!)
ноES6
Стандарт предлагает использоватьlet
иconst
заменятьvar
ключевое слово, чтобы «создать область блока». То есть приведенный выше код изменяется следующим образом, и область действия на уровне блоков действительна:
if (true) {
let a = 1;
}
console.log(a); // ReferenceError
о
let
иconst
Для получения более подробной информации перейдите напортал
Создать область
существуетjavascript
, у нас есть несколько способов создания/изменения областей видимости:
-
Определить функцию, создать действие функции (рекомендуется):
function foo () { // 创建了一个 foo 的函数作用域 }
-
использовать
let
иconst
Создать область блока (рекомендуется):for (let i = 0; i < 5; i++) { console.log(i); } console.log(i); // ReferenceError
-
try catch
создать область видимости (не рекомендуется),err
существует только вcatch
В статье:try { undefined(); // 强制产生异常 } catch (err) { console.log( err ); // TypeError: undefined is not a function } console.log( err ); // ReferenceError: `err` not found
-
использовать
eval
Лексическая область видимости «чит» (не рекомендуется):function foo(str, a) { eval( str ); console.log( a, b ); } var b = 2; foo( "var b = 3;", 1 ); // 1 3
-
использовать
with
Подмена лексической области видимости (не рекомендуется):function foo(obj) { with (obj) { a = 2; } } var o1 = { a: 3 }; var o2 = { b: 3 }; foo( o1 ); console.log( o1.a ); // 2 foo( o2 ); console.log( o2.a ); // undefined console.log( a ); // 2 -- 全局作用域被泄漏了!
Подводя итог, можно сказать, что есть два способа создания областей видимости: определить создание функции и разрешить создание константы.
Сценарии применения Scope
Одним из распространенных вариантов использования области видимости являетсямодульный.
Поскольку javascript изначально не поддерживает модульность, это приводит ко многим аппетитным проблемам, таким как загрязнение глобальной области видимости и конфликты имен переменных, раздутая структура кода и низкая возможность повторного использования. До введения формальных модульных решений разработчики думали об использовании функциональной области для создания модулей для решения таких проблем.
function module1 () {
var a = 1;
console.log(a);
}
function module2 () {
var a = 2;
console.log(a);
}
module1(); // => 1
module2(); // => 2
В приведенном выше коде создайтеmodule1
иmodule2
Две функции, представляющие модули, каждая из которых определяет переменную с тем же именемa
, из-за изолированного характера области действия функции эти две переменные хранятся в разных областях (не вложенных), механизм JS будет читать в разных областях при выполнении этих двух функций, а внешняя область не может получить доступ к внутренней функции.a
Переменная. Это аккуратно решаетзагрязнение глобального масштабаиконфликт имен переменныхпроблема; и из-за того, как написана функция, этот метод выглядит гораздо более инкапсулированным.
Однако описанный выше метод декларативного написания функций кажется несколько избыточным.module1
иmodule2
Само имя функции загрязняет глобальную область видимости. Продолжаем переписывать:
// module1.js
(function () {
var a = 1;
console.log(a);
})();
// module2.js
(function () {
var a = 2;
console.log(a);
})();
Перепишите объявление функции наНемедленно вызвать функциональное выражение (Immediately Invoked Function Expression
стенографияIIFE
), инкапсуляция лучше, а код лаконичнее, что решает проблему имени модуля, загрязняющего глобальную область видимости.
Самый простой способ отличить объявление функции от функционального выражения — посмотреть, начинается ли оно с ключевого слова function: если оно начинается с function, это объявление функции, иначе — функциональное выражение.
Код выше используетIIFE
Способ написания сильно изменился, мы можем снова усилить его, усилить его до версии обратной волны и дать ему право судить о внешней среде——право выбирать.
(function (global) {
if (global...) {
// is browser
} else if (global...) {
// is nodejs
}
})(window);
Пусть дальше несутся волны назад, нашей фантазии не хватит, чтобы представитьUMD
Модульный код:
// UMD 模块化
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// Node, CommonJS-like
module.exports = factory(require('jquery'));
} else {
// Browser globals (root is window)
root.returnExports = factory(root.jQuery);
}
}(this, function ($) {
// methods
function myFunc(){};
// exposed public method
return myFunc;
}));
Я смотрю на модульные сценарии применения масштаба, и я действительно завидую. Если вы так же завистливы, как и я, и хотите узнать больше о модульности, пожалуйста, введитепортал.
Закрытие
После разговора о масштабах, давайте поговорим оЗакрытие.
Функции, которые могут обращаться к переменным внутри других функций, называютсяЗакрытие.
Приведенное выше определение труднее понять, если говорить простыми словами,Замыкание — это функция, определенная внутри функции, которая возвращается и вызывается извне.. Мы можем выразить это в коде:
function foo() {
var a = 2;
function bar() {
console.log( a );
}
return bar;
}
var baz = foo();
baz(); // 这就形成了一个闭包
Мы можем кратко проанализировать работающий процесс приведенного выше кода:
- На этапе компиляции объявляются переменные и функции и определяется область действия.
- запустить функцию
foo()
, который создаетfoo
Контекст выполнения функции, контекст выполнения хранится внутриfoo
Вся информация о переменных функциях, объявленная в . - функция
foo
После запуска внутренняя функцияbar
Назначить ссылку на внешнюю переменнуюbaz
,В настоящее времяbaz
Указатель указывает наbar
, так что даже если он находится вfoo
За пределами области он все еще может получитьfoo
внутренняя переменная. -
baz
выполняется внешне,baz
Внутренний исполняемый кодconsole.log
Получить из сферыa
Переменная, локальная область не найдена, продолжайте запрашивать родительскую область, найденаfoo
серединаa
переменная, возвращенная вconsole.log
,распечатать2
.
Выполнение замыкания выглядит как небольшой «читерство», использованный разработчиками —Обходя механизм контроля области, информацию о внутренней области также можно получить извне.. Эта особенность замыканий значительно обогащает стиль кодирования разработчиков и обеспечивает множество эффективных сценариев применения.
Сценарии применения замыканий
Замыкания применяются в основном в сценариях, где необходимо поддерживать внутренние переменные.
одноэлементный шаблон
Одноэлементный шаблон — это распространенный шаблон, который гарантирует наличие только одного экземпляра класса. Метод реализации обычно заключается в том, чтобы сначала определить, существует ли экземпляр, и, если он существует, вернуть его напрямую, в противном случае создать его и вернуть. Преимущество одноэлементного шаблона заключается в том, чтобы избежать накладных расходов памяти, вызванных повторным созданием экземпляров:
// 单例模式
function Singleton(){
this.data = 'singleton';
}
Singleton.getInstance = (function () {
var instance;
return function(){
if (instance) {
return instance;
} else {
instance = new Singleton();
return instance;
}
}
})();
var sa = Singleton.getInstance();
var sb = Singleton.getInstance();
console.log(sa === sb); // true
console.log(sa.data); // 'singleton'
Имитация частной собственности
javascript
нетjava
среднийpublic
private
Все методы и свойства, используемые в объекте, могут быть доступны, что создает угрозу безопасности, и любой разработчик может изменить внутренние свойства по своему усмотрению. Хотя уровень языка не поддерживает создание приватных свойств, мы можем использовать замыкания для имитации приватных свойств:
// 模拟私有属性
function getGeneratorFunc () {
var _name = 'John';
var _age = 22;
return function () {
return {
getName: function () {return _name;},
getAge: function() {return _age;}
};
};
}
var obj = getGeneratorFunc()();
obj.getName(); // John
obj.getAge(); // 22
obj._age; // undefined
карри
Карри (
currying
) — это метод преобразования функции, которая принимает несколько параметров, в функцию, которая принимает один параметр (первый параметр исходной функции) и возвращает новую функцию, которая принимает остальные параметры и возвращает результат.
Эта концепция немного абстрактна, на самом деле каррирование — это использование функций высшего порядка.javascript
общий вbind
Затем метод может быть реализован каррирующим способом:
Function.prototype.myBind = function (context = window) {
if (typeof this !== 'function') throw new Error('Error');
let selfFunc = this;
let args = [...arguments].slice(1);
return function F () {
// 因为返回了一个函数,可以 new F(),所以需要判断
if (this instanceof F) {
return new selfFunc(...args, arguments);
} else {
// bind 可以实现类似这样的代码 f.bind(obj, 1)(2),所以需要将两边的参数拼接起来
return selfFunc.apply(context, args.concat(arguments));
}
}
}
Одним из преимуществ карри является то, чтоповторное использование параметров, он может генерировать другую совершенно новую функцию на основе входящих параметров, посмотрите на следующую функцию оценки типа:
function typeOf (value) {
return function (obj) {
const toString = Object.prototype.toString;
const map = {
'[object Boolean]' : 'boolean',
'[object Number]' : 'number',
'[object String]' : 'string',
'[object Function]' : 'function',
'[object Array]' : 'array',
'[object Date]' : 'date',
'[object RegExp]' : 'regExp',
'[object Undefined]' : 'undefined',
'[object Null]' : 'null',
'[object Object]' : 'object'
};
return map[toString.call(obj)] === value;
}
}
var isNumber = typeOf('number');
var isFunction = typeOf('function');
var isRegExp = typeOf('regExp');
isNumber(0); // => true
isFunction(function () {}); // true
isRegExp({}); // => false
сквозьtypeOf
Передавая строковые параметры различных типов, можно сгенерировать соответствующую функцию оценки типа, которую можно повторно использовать в бизнес-коде в качестве синтаксического сахара.
Проблема с замыканиями
Из приведенного выше введения мы можем знать, что использование замыканий очень обширно, поэтому можем ли мы использовать замыкания часто? Нет, потому что чрезмерное использование замыканий может привести к проблемам с производительностью, или посмотрите на фрагмент кода, продемонстрированный ранее:
function foo() {
var a = 2;
function bar() {
console.log( a );
}
return bar;
}
var baz = foo();
baz(); // 这就形成了一个闭包
На первый взгляд кажется, что проблемы нет, однако это может вызватьутечка памяти.
мы знаем,javascript
Внутренний механизм сборки мусора использует сборку с подсчетом ссылок: то есть, когда на переменную в памяти ссылаются один раз, счетчик увеличивается на единицу. Механизм сборки мусора опрашивает эти переменные в фиксированное время и будет учитываться как0
Переменная помечается как недопустимая и очищается для освобождения памяти.
В приведенном выше коде теоретическиfoo
Область действия функции изолирует внешнюю среду, и все ссылки на переменные выполняются внутри функции.foo
После завершения операции внутренние переменные должны быть уничтожены, а память восстановлена. Однако замыкания приводят к тому, что глобальная область всегда имеетbaz
переменная ссылаетсяfoo
Внутреннийbar
функция, а значитfoo
внутренне определенныйbar
Количество ссылок на функции всегда1
, механизм запуска мусора не может его уничтожить. Худший,bar
Можно также использовать родительскую областьfoo
Информация о переменных в , то они, естественно, не могут быть уничтожены... Движок JS не может судить, когда вы вызовете функцию закрытия, и может только удерживать эти данные в памяти.
Такая ситуация, когда использование памяти не может быть освобождено из-за чрезмерного использования замыкания, называется утечкой памяти.
утечка памяти
Утечка памяти относится к явлению, когда часть памяти больше не используется приложением по какой-то причине, эта часть памяти не возвращается операционной системе или пулу памяти. Утечки памяти могут привести к зависанию или сбою приложений.
Причин утечек памяти много, кроме замыканий есть ещеНепреднамеренное создание глобальных переменных. Первоначальное намерение разработчика состояло в том, чтобы использовать переменную как локальную переменную, но забыл написатьvar
Вызывает утечку переменной в глобальную:
function foo() {
b = 2;
console.log(b);
}
foo(); // 2
console.log(b); // 2
иDOM
привязки событий, удалитьDOM
Если вы забудете отменить регистрацию метода события, привязанного к элементу, это также вызовет утечку памяти:
const wrapDOM = document.getElementById('wrap');
wrapDOM.onclick = function (e) {console.log(e);};
// some codes ...
// remove wrapDOM
wrapDOM.parentNode.removeChild(wrapDOM);
Устранение неполадок с утечками памяти
Возможно, все слышали о печально известной «утечке памяти», но перед лицом обширного наследственного кода трудно найти место, вызвавшее утечку памяти. Здесь мы по-прежнему используем инструменты разработчика Google,Chrome
браузер,F12
Откройте инструменты разработчика, я нашел демо-версию веб-сайта ES6 учителя Руана Ифэна.
Performance
Нажмите эту кнопку, чтобы начать запись, затем переключитесь на веб-страницу для работы, нажмите после завершения записи.stop
кнопку, и инструменты разработчика будут записывать различные данные текущего приложения с момента записи.
проверилJS Heap
, синяя линия, показанная ниже, представляет изменение информации о памяти кучи JS во время этого процесса записи.
Большой парень сказал, что по этой синей линии можно судить, есть ли утечка памяти:Если синяя линия продолжает расти, это, по сути, утечка памяти.. На самом деле, я думаю, что говорить об этом предвзято. Увеличение использования памяти кучи JS не обязательно является утечкой памяти. Это может означать только то, что есть много невысвобожденной памяти. Что касается того, действительно ли эта память используется, или это действительно утечка памяти, требуется дальнейшее расследование.
memory
Использование памяти можно определить более точно с помощью параметра Память инструментов разработчика.
Когда был сделан первый снимок, окно инструментов разработчика уже показывало очень подробное использование памяти.
Объяснение поля:
-
Constructor
— Тип ресурса, который занимает память -
Distance
— расстояние опорного уровня от текущего объекта до корня -
Shallow Size
— Память, занимаемая объектом (за исключением памяти, занимаемой другими объектами, на которые имеются внутренние ссылки) (единица измерения: байты) -
Retained Size
— Общая память, занимаемая объектом (включая память, занимаемую другими объектами, на которые имеются внутренние ссылки) (единица измерения: байты)
Разверните каждый элемент, чтобы просмотреть более подробную информацию о данных.
Мы снова переключаемся на веб-страницу, продолжаем несколько раз, а затем снова делаем снимок.
На это следует обратить особое внимание#Delta
, если это положительное значение, это означает, что создается больше памяти и высвобождается меньше памяти. Элемент замыкания в нем, если он имеет положительное значение, значит, есть утечка памяти.
Перейдем к коду, чтобы найти проблему утечки памяти:
решение проблемы с утечкой памяти
-
Используйте строгий режим, чтобы избежать непреднамеренных утечек глобальных переменных:
"use strict"; function foo () { b = 2; } foo(); // ReferenceError: b is not defined
-
обрати внимание на
DOM
В жизненном цикле не забудьте отвязать связанные события на этапе уничтожения:const wrapDOM = document.getElementById('wrap'); wrapDOM.onclick = function (e) {console.log(e);}; // some codes ... // remove wrapDOM wrapDOM.onclick = null; wrapDOM.parentNode.removeChild(wrapDOM);
Или вы можете использовать делегирование событий для единообразной обработки событий, чтобы уменьшить дополнительные накладные расходы памяти, вызванные привязкой событий:
document.body.onclick = function (e) { if (isWrapDOM) { // ... } else { // ... } }
-
Избегайте чрезмерного использования замыканий.
Большинство утечек памяти вызвано ошибками в коде. Десятки тысяч кодов, первый стандартизированный, код не стандартизированный, и разработаны две линии разрывов.
Суммировать
-
javascript
На уровне языка изначально поддерживаются только два типа областей:глобальная областьиобъем функции. Глобальная область существует, когда программа запускается, а область действия функции доступна только тогда, когда функция определена, и между ними существует связь. - Области могут быть вложенными, мы называем это отношением вложенности какцепочка прицелов.
- Когда исполняемый код запрашивает переменные в области видимости, он может запрашивать тольколокальная областьиверхняя сфера, не может найти внутреннюю область действия функции. Когда JS-движок ищет переменные, он сначала запрашивает локальную область, возвращает, когда она найдена, а затем запрашивает верхнюю область, если она не может быть найдена... Слой за слоем, до глобальной области.
-
javascript
используется в«лексический объем», поэтому область видимости функции определяется при определении функции, независимо от того, где функция выполняется. - Функция, которая имеет доступ к переменной внутри другой функции, называетсяЗакрытие.Суть замыкания заключается в использовании механизма области действия для достижения цели доступа к внутренней области видимости из внешней области видимости.
- Замыкания используются в самых разных сценариях, но чрезмерное использование приведет к тому, что пространство памяти, занятое переменными в замыкании, не сможет быть освобождено, что приведет кутечка памятиПроблема.
- мы можем использовать
chrome
Инструменты разработчика ищут в коде код, вызвавший утечку памяти. - Несколько способов избежать утечек памяти: избегать использования глобальных переменных,
DOM
Связывайте события и избегайте чрезмерного использования замыканий. Самое главное — это спецификация кода. 😃
Эта статья была включена вСтолбец «Руководство по фронтенд-интервью»
Связанные ссылки
- «JavaScript, которого вы не знаете»
- «Вы не знаете JS: мое понимание областей видимости и замыканий»
- Closures - JavaScript | MDN
- Лексическая область видимости и динамическая область видимости в JavaScript
- Вы не знаете JS — область действия и замыкания
- Говоря об объявлении и назначении переменных Js с точки зрения LHS и RHS
- предварительное интервью
- Запишите опыт устранения неполадок с утечкой памяти во внешнем интерфейсе.
Рекомендуемый прошлый контент
- Тщательно разбирайтесь в троттлинге и анти-тряске
- [Основные] Принципы и применение протоколов HTTP и TCP/IP
- [Combat] webpack4 + ejs + express перенесет вас в многостраничную архитектуру проекта приложения
- Цикл событий в браузере
- Интервьюер: Расскажите мне о контексте казни.
- Интервьюер: Расскажите о цепочке прототипов и наследовании.
- Интервьюер: Расскажите о модульности в JS.
- Интервьюер: Давайте поговорим о let и const.