Интервьюер: Расскажите о масштабе и закрытиях.

JavaScript
Интервьюер: Расскажите о масштабе и закрытиях.

Одна из самых фундаментальных моделей почти любого языка — хранить значения в переменных и извлекать или изменять эти значения позже. Возможность сохранять и извлекать значения в переменных дает состояние программы. Это приводит к двум вопросам: где хранятся эти переменные? Как программа находит их, когда они нужны? Чтобы ответить на эти вопросы, требуется четко определенный набор правил, определяющих, как хранятся переменные и как их найти. Мы называем этот набор правил: область действия.

LHS и RHS Запросы

Прежде чем говорить об области видимости в javascript, я подумал, что было бы полезно сначала понять запросы LHS и RHS.

Несмотря на то чтоjavascriptОн считается интерпретируемым/динамическим языком, но на самом деле это компилируемый язык. Как правило, требуется периодjavascriptкода, есть две важные вещи:JS-движокипереводчик. Первая похожа на роль менеджера, отвечающего за планирование различных ресурсов, необходимых для работы всей программы; вторая является лишь частью первой, отвечающей заjavascriptИсходный код компилируется в машинные инструкции, которые машина может распознать, а затем передается движку для запуска.

компилировать

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

  1. сегментация слов / лексический анализ: компилятор сначала разбивает последовательность символов на значимые сегменты (для языка), называемые токенами, например.var a = 2;. Эта программа, вероятно, будет разбита на следующий токен:var,a,=,2;.
  2. разбор / разбор: компилятор преобразуетtokenпоток (массив) в «абстрактное синтаксическое дерево» (AST —— Abstract Syntax Tree), который представляет собой грамматическую структуру программы.
  3. генерация кода: компилятор преобразует абстрактное синтаксическое дерево, сгенерированное на предыдущем шаге, в машинные инструкции, ожидая выполнения движка.

воплощать в жизнь

Компилятор работает как тигр и генерирует кучу машинных инструкций, движок 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полученный из области действия функции.

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

Как показано на рисунке, приведенный выше код имеет в общей сложности три уровня вложенности области видимости, а именно:

  1. глобальная область
  2. fooсфера
  3. 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, у нас есть несколько способов создания/изменения областей видимости:

  1. Определить функцию, создать действие функции (рекомендуется):

    function foo () {
      // 创建了一个 foo 的函数作用域
    }
    
  2. использоватьletиconstСоздать область блока (рекомендуется):

    for (let i = 0; i < 5; i++) {
      console.log(i);
    }
    
    console.log(i); // ReferenceError
    
  3. try catchсоздать область видимости (не рекомендуется),errсуществует только вcatchВ статье:

    try {
     undefined(); // 强制产生异常
    }
    catch (err) {
     console.log( err ); // TypeError: undefined is not a function
    }
    
    console.log( err ); // ReferenceError: `err` not found
    
  4. использоватьevalЛексическая область видимости «чит» (не рекомендуется):

    function foo(str, a) {
     eval( str );
     console.log( a, b );
    }
    
    var b = 2;
    
    foo( "var b = 3;", 1 ); // 1 3
    
  5. использовать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(); // 这就形成了一个闭包

Мы можем кратко проанализировать работающий процесс приведенного выше кода:

  1. На этапе компиляции объявляются переменные и функции и определяется область действия.
  2. запустить функциюfoo(), который создаетfooКонтекст выполнения функции, контекст выполнения хранится внутриfooВся информация о переменных функциях, объявленная в .
  3. функцияfooПосле запуска внутренняя функцияbarНазначить ссылку на внешнюю переменнуюbaz,В настоящее времяbazУказатель указывает наbar, так что даже если он находится вfooЗа пределами области он все еще может получитьfooвнутренняя переменная.
  4. 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, если это положительное значение, это означает, что создается больше памяти и высвобождается меньше памяти. Элемент замыкания в нем, если он имеет положительное значение, значит, есть утечка памяти.

Перейдем к коду, чтобы найти проблему утечки памяти:

решение проблемы с утечкой памяти

  1. Используйте строгий режим, чтобы избежать непреднамеренных утечек глобальных переменных:

    "use strict";
    
    function foo () {
    	b = 2;
    }
    
    foo(); // ReferenceError: b is not defined
    
  2. обрати внимание на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 {
            // ...
        }
    }
    
  3. Избегайте чрезмерного использования замыканий.

Большинство утечек памяти вызвано ошибками в коде. Десятки тысяч кодов, первый стандартизированный, код не стандартизированный, и разработаны две линии разрывов.

Суммировать

  1. javascriptНа уровне языка изначально поддерживаются только два типа областей:глобальная областьиобъем функции. Глобальная область существует, когда программа запускается, а область действия функции доступна только тогда, когда функция определена, и между ними существует связь.
  2. Области могут быть вложенными, мы называем это отношением вложенности какцепочка прицелов.
  3. Когда исполняемый код запрашивает переменные в области видимости, он может запрашивать тольколокальная областьиверхняя сфера, не может найти внутреннюю область действия функции. Когда JS-движок ищет переменные, он сначала запрашивает локальную область, возвращает, когда она найдена, а затем запрашивает верхнюю область, если она не может быть найдена... Слой за слоем, до глобальной области.
  4. javascriptиспользуется в«лексический объем», поэтому область видимости функции определяется при определении функции, независимо от того, где функция выполняется.
  5. Функция, которая имеет доступ к переменной внутри другой функции, называетсяЗакрытие.Суть замыкания заключается в использовании механизма области действия для достижения цели доступа к внутренней области видимости из внешней области видимости.
  6. Замыкания используются в самых разных сценариях, но чрезмерное использование приведет к тому, что пространство памяти, занятое переменными в замыкании, не сможет быть освобождено, что приведет кутечка памятиПроблема.
  7. мы можем использоватьchromeИнструменты разработчика ищут в коде код, вызвавший утечку памяти.
  8. Несколько способов избежать утечек памяти: избегать использования глобальных переменных,DOMСвязывайте события и избегайте чрезмерного использования замыканий. Самое главное — это спецификация кода. 😃

Эта статья была включена вСтолбец «Руководство по фронтенд-интервью»

Связанные ссылки

Рекомендуемый прошлый контент

  1. Тщательно разбирайтесь в троттлинге и анти-тряске
  2. [Основные] Принципы и применение протоколов HTTP и TCP/IP
  3. [Combat] webpack4 + ejs + express перенесет вас в многостраничную архитектуру проекта приложения
  4. Цикл событий в браузере
  5. Интервьюер: Расскажите мне о контексте казни.
  6. Интервьюер: Расскажите о цепочке прототипов и наследовании.
  7. Интервьюер: Расскажите о модульности в JS.
  8. Интервьюер: Давайте поговорим о let и const.