ilyachalov (ilyachalov) wrote,
ilyachalov
ilyachalov

Categories:

Учебник по JavaScript: ч.1: работа с объектом функции

Начало тут: Учебник по JavaScript: ч.1: var, глобальный объект, объект функции.

Понравилась задача «Установка и уменьшение значения счётчика» к подразделу 6.6 «Объект функции, NFE» учебника.

В задаче предлагается менять функцию makeCounter (по-русски «создать счетчик»), но код этой функции не дается, потому что подразумевается, что ученик читал текущий и предыдущие подразделы учебника, в которых эта функция разбиралась.

Есть два варианта этой функции.

1. Вариант из подраздела 6.3 «Замыкание» (для хранения значения счетчика используется локальная переменная count):
function makeCounter() {
    let count = 0;

    return function() {
        return count++;
    };
}

2. Вариант из текущего подраздела 6.6 (для хранения значения счетчика используется свойство count, которое программист добавляет в функцию counter, возвращаемую функцией makeCounter):
function makeCounter() {
    function counter() {
        return counter.count++;
    };

    counter.count = 0;

    return counter;
}

Для тестирования этой функции в обоих вариантах можно использовать следующий код:
let counter = makeCounter(); // создаём счетчик, который используем ниже
alert( counter() ); // 0
alert( counter() ); // 1
alert( counter() ); // 2

Итак, в задаче требуется написать к функции counter, возвращаемой функцией makeCounter, два метода: counter.set(value), который должен устанавливать счетчик в значение value, и counter.decrease(), который должен уменьшать значение счетчика на 1.

В задании сказано, что решение можно сделать в обоих вышеизложенных вариантах, но сами авторы приводят решение только для первого варианта (с хранением значения счетчика в локальной переменной count). Я же решил задачу в обоих вариантах.

Для тестирования обоих полученных решений можно использовать следующий код:
let counter = makeCounter(); // создаём счетчик, который используем ниже

alert( counter() ); // 0
alert( counter() ); // 1

counter.set(10);

alert( counter() ); // 10
alert( counter() ); // 11

counter.decrease();

alert( counter() ); // 11
alert( counter() ); // 12

1. Вариант решения с хранением значения счетчика в локальной переменной count:
function makeCounter() {
    let count = 0;                  // (*)

    function counter() {            // (*)
        return count++;
    }

    counter.set = function(value) { // (*)
        count = value;
    };

    counter.decrease = function() { // (*)
        count--;
    };

    return counter;
}
Что интересно, куски кода, помеченные в этом решении звездочкой (*), можно безболезненно менять местами в любом порядке внутри функции makeCounter, пока все они находятся до инструкции return counter; (впрочем, объявление функции counter можно сделать внутри функции makeCounter и после инструкции return counter;). Таковы свойства области видимости переменных и функций в языке JavaScript, эта тема уже разбиралась в учебнике ранее.

2. Вариант решения с хранением значения счетчика в свойстве count функции counter, возвращаемой функцией makeCounter:
function makeCounter() {
    counter.count = 0;              // (*)

    function counter() {            // (*)
        return counter.count++;
    }

    counter.set = function(value) { // (*)
        counter.count = value;
    };

    counter.decrease = function() { // (*)
        counter.count--;
    };

    return counter;
}
В этом решении куски кода, помеченные звездочкой (*), можно так же менять местами, как это было описано для предыдущего решения.

Кроме этого, в принципе, добавление и инициализацию свойства count к функции counter, а также добавление методов к этой функции можно вообще вынести из функции makeCounter и прописать после запуска функции makeCounter, но до использования этого свойства и этих методов (для первого варианта решения такое невозможно). Вот так:

3.
function makeCounter() {
    function counter() {            // (*)
        return counter.count++;
    }

    return counter;
}

let counter = makeCounter(); // создаём счетчик, который используем ниже

counter.count = 0;                  // (*)

counter.set = function(value) {     // (*)
    counter.count = value;
};

counter.decrease = function() {     // (*)
    counter.count--;
};

// дальнейшее тестирование

Тут можно видеть разницу между использованием локальных переменных (замыкание) и свойств функций, как объектов. Локальную переменную count из первого варианта решения нельзя поменять извне функции makeCounter, а свойства и методы функции counter можно менять хоть внутри функции makeCounter, хоть снаружи. По идее, в разных случаях могут понадобиться все перечисленные варианты решения обсуждаемой задачи.
Tags: Образование, Программирование
Subscribe

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 0 comments