Открыть меню    

Замыкания js

Объект LexicalEnvironment

Javascript

function sayHi(name){
    // LexicalEnvironment = { name: 'Vasya', phrase: undefined }
    // локальные переменные являются свойствами специального объекта - LexicalEnvironment

    var phrase = 'Hello' + name;

    // LexicalEnvironment = { name: 'Vasya', phrase: 'Hello ...' }

    alert(phrase);
}

    //sayHi('Vasya');

// объект LexicalEnvironment создается при вызове функции
// когда функция заканчивается обычно LexicalEnvironment "выбрасывается", потому что
// больше не нужен - память при этом освобождается

свойство [[Scope]]

Javascript

//Функция может использовать переменные, которые объявлены вне ее

var b = 2;

function f(a) {

//  f.[[Scope]] = window

    // Когда функция объявляется (создается), то функция объявляется в каком-то контексте
    // в данном случае в глобальном объекте window
    // свойство объекта функции f.[[Scope]] записывается ссылка на window
    // свойство  [[Scope]] объявляется 1 раз в момент СОЗДАНИЯ функции.
    // Это свойство играет важную роль в поиске переменных:
    // то есть переменная изначально ищется в LexicalEnvironment, а затем по ссылке
    // на внешнее окружение и ее значение ставится по Scope функции

// LexicalEnvironment = { a: 1 } -> window

    // Объекту LexicalEnvironment добавляется ссылка на внешнее окружение и
    // ее значение ставится по Scope функции, в данном случае window

    alert(a + b);

}

    //f(1);

// За счет чего функции удается получить доступ к переменной, которая в ней не объявлна?
// В js существует скрытое свойство [[Scope]]

Вложенные функции

Javascript

function sayHi(name, age){
    // function Declaraton обрабатываются в момент входа, при создании LexicalEnvironment.
    // function expression обрабатываются в момент, когда код выполнения до них доберется
    // (при создании LexicalEnvironment function expression равны undefined).
    // затем после выполнени функции (sayHi) обе эти функции будет уничтожены вместе
    // с объектом переменных (LexicalEnvironment) и память будет очистена

    // НО БЫВАЮТ СИТУАЦИИ, КОГДА ОБЪЕКТ ПЕРЕМЕННЫХ (LexicalEnvironment) НЕ УНИЧТОЖАЕТМЯ (*)

    alert(makePhrase(name));

    // ----------------

    function makePhrase() {
        return chooseWord() + ', ' + name;
    }

    function chooseWord() {
        return age > 18 ? 'Здравствуйте' : 'Привет';
    }

}


sayHi('Петька', 18);
sayHi('Василий Иванович', 35);

ЗАМЫКАНИЯ (*)

Javascript

// замыканием называется функция вместе со всеми переменными, которые ей доступны
// доступ к переменной, которая не находится в самой функции, а находится во внешнем объекте переменных называется
// доступом через замыкание

function sayHi(name, age){
    //LexicalEnvironment = {
        //  name: 'Петька',
        //  age: 18,
        //  makePhrase: function
        //  chooseWord: function
    //} -> window

    // НО БЫВАЮТ СИТУАЦИИ, КОГДА ОБЪЕКТ ПЕРЕМЕННЫХ (LexicalEnvironment) НЕ УНИЧТОЖАЕТСЯ:

    // ВО ВРЕМЯ ВЫПОЛНЕНИЯ СОЗДАЕТСЯ ФУНКЦИЯ И ВОЗВРАЩАЕТСЯ

    // ПРИ СОЗДАНИИ ФУНКЦИЯ ПОЛУЧАЕТ [[Scope]] равный текущему объекту переменных (LexicalEnvironment)
    // ТАК КАК НА ОБЪЕКТ ПЕРЕМЕННЫХ (LexicalEnvironment) ЕСТЬ ССЫЛКА, ТО ОН НЕ УНИЧТОЖАЕТСЯ

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

    return function () { // [[Scope]] = LexicalEnvironment
        alert(makePhrase(name));
    }

    // ----------------

    function makePhrase() {
        return chooseWord() + ', ' + name;
    }

    function chooseWord() {
        return age > 18 ? 'Здравствуйте' : 'Привет';
    }

}

// ф-я (work) выше может понадобиться, например, при вызове ф-и в будущем (при нажатии по кнопке)

    // функция, которая возвращена во внешний код, как work, ссылается через свое свойство Scope
    // на LexicalEnvironment, поэтому он остается в памяти. и будет оставаться там, пока на него есть хоть одна ссылка
    // LexicalEnvironment держит в памяти функция work
var work = sayHi('Петька', 18);

Комментарии к статье

аватарка пользователя
2016-09-29
Андрей

Огромное спасибо за статью! Только с ее помощью наконец разобрался сразу со scope, LexicalEnvironment и замыканиями. Было бы здорово еще получить информацию по VariableEnvironment.

Корза деревянная мозаика