Замыкания и их приложения

JavaScript

Название: Замыкания и их приложения дата: 2019-04-25 17:00:00 теги: -JavaScript
-closure categories: JavaScript password: tgfe abstract: Welcome to my blog, enter password to read. message: Welcome to my blog, enter password to read.

Front-end разработчики должны быть знакомы с точки зрения закрытия, Мы все знаем, что понятие закрытия относится к функции, которая имеет доступ к переменным в области действия другой функции. Итак, каковы же практические применения замыканий в js?

Среда выполнения и цепочка областей видимости

Чтобы понять замыкания, вы должны сначала понять среду выполнения и область применения js.

Концепция слишком длинная, чтобы смотреть сериал:

Среда выполнения определяет другие данные, к которым имеет доступ переменная или функция, что определяет их соответствующее поведение. С каждой средой выполнения связана коллекция объектов переменных [[scope]]. Все переменные и функции, определенные в среде, хранятся в этом объекте. Эта коллекция называется цепочкой областей видимости среды.

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

Когда код выполняется в контексте функции, создается цепочка областей видимости переменных объектов. Передний конец цепочки областей видимости всегда представляет собой переменный объект, в котором находится исполняемый в данный момент код. Если среда является функцией, используйте ее активный объект как объект переменной. Активный объект изначально содержит только одну переменную, объект arguments (этот объект не существует в глобальной среде). Следующий объект в цепочке областей действия происходит из содержащей (внешней) среды, а следующая переменная — из среды следующей переменной. Таким образом, он переходит в глобальную среду выполнения; переменный объект глобальной среды выполнения всегда является последним объектом в цепочке областей видимости. Когда контекст среды выполнения уничтожается, активный объект также уничтожается.

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

Суммировать:

  • У каждой функции есть среда выполнения, а среда выполнения связана с переменным объектом.Набор переменных объектов называется цепочкой области видимости.
  • Передний конец цепочки областей действия — это объект переменной, в котором находится текущий исполняемый код, а следующий объект — это внешняя функция, которая продолжается до глобальной переменной.
  • Разрешение идентификатора — это процесс работы в обратном направлении от внешнего интерфейса по цепочке областей видимости.
  • После выполнения кода среда, в которой он находится, будет уничтожена.Глобальной средой выполнения в вебе является объект окна, а глобальная среда будет уничтожена при выходе из приложения.

Определенное закрытие

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

Обычный способ создания замыканий — создание функции внутри другой функции.

В JavaScript замыкание — это комбинация функции и области действия этой функции. Концептуально в js все функции являются замыканиями (функции — это объекты, а функции имеют связанную с ними цепочку областей видимости).

大多数函数被调用时(invoked),使用的作用域和他们被定义时(defined)使用的作用域是同一个作用域,这种情况下,闭包神马的,无关紧要。但是,当他们被invoked的时候,使用的作用域不同于他们定义时使用的作用域的时候,闭包就会变的非常有趣,并且开始有了很多的使用场景,这就是你之所以要掌握闭包的原因。 использовать:

  • Прочитайте переменную внутри функции.
  • Всегда держите значения этих переменных в памяти. не будет автоматически очищаться после вызова f1.
  • Локальные переменные для удобного контекста вызова. Хорошо подходит для инкапсуляции кода.

Вопросы для интервью помогают пищеварению

var scope = "window scope"; 
function checkScope() {
    var scope = "local scope";
    function f() {
        return scope;
    }
    return f();
}
checkScope();   //=> "local scope"
  • При вызове checkScope возвращаем f(), запускаем внутреннюю вложенную функцию f, f ищет область видимости переменной изнутри наружу по цепочке областей видимости, находит «локальную область видимости» и останавливает поиск, поэтому функция возвращает «локальную область действия»;
var scope = "window scope"; 
function checkScope() {
    var scope = "local scope";
    function f() {
        return scope;
    }
    return f;
}
checkScope()();   //=> "local scope"
  • Когда вызывается checkScope, возвращается вложенная функция f, поэтому, когда выполняется предложение checkScope()(), фактически выполняется f(), и функция f возвращает переменную области видимости. • А как насчет поиска области действия переменной в домене?
  • Основные правила домена способа слова: цепь охвата, используемая при выполнении функции, вместо выполнения цепочки области. Вложенные функции f (), когда определяется, в цепочке области объема переменной область - это связанное значение - это «локальный объем» вместо «окна Scope», поэтому результат вышеуказанного кода? Это верно, это «локальный объем». Это волшебная особенность замыкания: закрытие может захватить внешнюю функцию связывания локальных переменных и параметров, даже если вызов внешней функции окончен.
var scope = "window scope"; 
function checkScope() {
    var scope = "local scope";
    function f() {
        return this.scope;
    }
    return f;
}
checkScope()();   //=> "window scope"
  • this замыкания указывает на this места, где оно определено В нестрогом режиме this внутри функции указывает на глобальный объект (в строгом режиме this не определено), а this функции checkScope указывает на объект окна, поэтому возвращает область окна

Сценарии применения замыканий

Событие Bind click для цикла узла

Текущая страница имеет 5 кнопок, требование состоит в том, чтобы при нажатии каждой кнопки отображался соответствующий номер.

//html-код

<!DOCTYPE html>
<html>
<head>
     <meta charset="UTF-8">
</head>
<body>
    <button>Button0</button>
    <button>Button1</button>
    <button>Button2</button>
    <button>Button3</button>
    <button>Button4</button>
</body>
</html>

//js

for(var i = 0;i<btnList.length;i++){
	//错误的代码 onclick是异步触发的,
	btnList[i].onclick = function(){
		console.log(i)
	}
 
	//正确的代码
	//采用“立即执行函数Immediately-Invoked Function Expression (IIFE)”的方式创建作用域
	(function(i){
		btnList[i].onclick = function(){
			console.log(i)
		}
	})(i);
}

сделать Немедленно выполнить функцию нет я

Продолжение жизни локальных переменных

img объекты часто используются для создания отчетов о данных, например:

var report = function(src) {
    var img = new Image();
    img.src = src;
}
report('http://xxx.com/getUserInfo');

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

Следовательно, мы можем использовать замыкание, чтобы закрыть объект img, чтобы решить проблему потери данных:

var report = (function() {
    var imgs = [];
    return function(src) {
        var img = new Image();
        imgs.push(img);
        img.src = src;
    }
})()


 (function(){
        //i在外部就不认识啦
        for(var i=0;i<count;i++){}
  })();
  console.log(i);//报错,无法访问

кэшировать результаты

сделать Передача сложных данных Реализация реакции vue https

var fn=function(){
    var sum=0;
    for(var i=0;i<arguments.length;i++){
        sum+=arguments[i];
    }
    return sum;
}
console.log(fn(1,2));//3
 
//优化版本
var fn=(function(){
    var cache={}//将结果缓存到该对象中
    return function(){
        var str=JSON.stringify(arguments);
        if(cache[str]){//判断缓存中是否存在传递过来的参数,存在直接返回结果,无需计算
            return cache[str];
        }else{//进行计算并返回结果
            var sum=0;
            for(var i=0;i<arguments.length;i++){
                sum+=arguments[i];
            }
            return cache[str]=sum;
        }
    }
})()

Режим конфигурации шаблона дизайна

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

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

// 构造器模式
function Car(model, year, miles){
	this.model = model;
	this.year = year;
	this.miles = miles;

	Car.prototype.toString = function(){
		return this.model + 'has done ' + this.miles + ' miles';
	}
}
 
var civic = new Car('honda civic', 2019, 2000);
console.log(civic.toString()); 
  • JavaScript не поддерживает концепцию класса, но поддерживает специальную функцию конструктора (конструктора), используемую с объектами.Добавляя ключевое слово new перед конструктором, JavaScript получает команду создать экземпляр нового объекта, как если бы он был конструктором, и члены объекта определяются конструктором, определением функции.
  • Функции, такие как TOSTRING здесь, переопределены каждый раз, когда создается новый экземпляр, который не является идеальным, TOSTRING должен быть разделен среди всех экземпляров автомобильной конструкции. Поэтому поставьте ToString на прототип (объект прототипа) автомобиля, все экземпляры, построенные на машине, будут получать доступ к тому же объекту прототипа и получить метод ToString. Здесь ToString - это замыкание, а функция может получить доступ к модели, милям и одно годам переменные в экземпляре.

сделать Расположение прототипа

Модульный режим

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

var myNamespace = (function(){
    var obj = {};
    // 私有计数器变量
    var myPrivateVar = 0;
    
    // 记录所有参数的私有函数
    var myPrivateMethods  = function(bar){
        console.log('my privateVar in private = '+ bar);
    }
    
    //公有变量
    var myPublicVar = 'foo';
    // 调用私有变量和函数的公有函数
    function myPublicMethods(bar){
        // 增加私有计数器值
        myPrivateVar = bar;
        console.log('my privateVar in public = '+ myPrivateVar);
        // 调用私有函数 并传入参数
        myPrivateMethods(bar);
    }
    
    obj.myPublicVar = myPublicVar;
    obj.myPublicMethods = myPublicMethods;
    
    return obj;
    
})();

// myNamespace.myPrivateVar;
// 用户可以调用公有函数,访问和变更私有函数及私有变量
myNamespace.myPublicMethods('user input');

Режим модуля с использованием комплектации пакета «Частный» статус и ткани. Он предоставляет общий пакет гибридный режим / частные методы и переменные, чтобы предотвратить его утечку глобальному объему и конфликтует с другим интерфейсом для разработчиков. С помощью этого режима только для возврата всего API, в то время как все остальное осталось в частном закрытом мешке. В модульном режиме общие части (закрывающиеся) могут быть связаны с закрытой частью, но не в контакте с внешней частью частной части класса, а MyPrivateMeths MyPrivateVar модуль является частным, поэтому другие части приложения не могут читать напрямую Отказ Вместе с наличием только модулей закрытия.