Функция-конструктор и замыкание

Нужно создать функцию, которая бы работала так:

let storage = createStorage();
storage.setItem('userName': 'Alex');
storage.getItem('userName'); // 'Alex'
storage.getItem('userAge'); // null
storage.hasItem('userAge'); // false
storage.setItem('userAge': 28);
storage.hasItem('userAge'); // true
storage.length(); // 2
storage.removeItem('userName');
storage.length(); // 1
storage.clear();
storage.length(); // 0

Додумалась только до функции-конструктора, а тема сама замыкание и области видимости. Не очень понятно, где и как их применить.

function createStorage (userName, userAge) {
    this.userName = userName;
    this.userAge = userAge;
    
}
let storage = new createStorage();
storage.setItem('userName', 'Alex');
storage.getItem('userName'); 

дальше этого не идет :(


Ответы (3 шт):

Автор решения: Aziz Umarov

По функционалу ваше замыкание это обычный Map

Вам нужно переименовать методы Map под ваши и всё.

storage.getItem -> map.get
storage.setItem -> map.set
storage.length -> map.size
storage.hasItem -> map.has
storage.removeItem -> map.delete
storage.clear -> map.clear

Будет это все примерно так

createStorage(){
 let map = new Map();
 return {
   getItem: function (key) { return map.get(key)? map.get(key) : null; }
   .....
 };// return
}

UPD нужно сделать было так

function createStorage() {
    let map = new Map();
    return {
        getItem: function (key) { return map.get(key)? map.get(key) : null; },
        setItem: function (key, value) { return map.set(key, value); },
        hasItem: function (key) { return map.has(key); },
        length: function () { return map.size; },
        removeItem: function(key) { return map.delete(key); },
        clear: function() {return map.clear();}
   
    }
}

let storage = createStorage();
storage.setItem('userName', 'Alex');
storage.getItem('userName'); // 'Alex'
console.log(storage.getItem('userName'));

storage.getItem('userAge'); // null
console.log(storage.getItem('userAge'));

storage.hasItem('userAge'); // false
console.log(storage.hasItem('userAge'));

storage.setItem('userAge', 28);
console.log(storage.getItem('userAge'));

storage.hasItem('userAge'); // true
console.log(storage.hasItem('userAge'));

storage.length(); // 2
console.log(storage.length());

storage.removeItem('userName');
console.log(storage.getItem('userName'));

storage.length(); // 1
console.log(storage.length());

storage.clear();
storage.length(); // 0
console.log(storage.length());

или чуть короче вариант

function createStorage() {
    let map = new Map();
    return {
        getItem: key => map.get(key)? map.get(key) : null,
        setItem: (key, value) => map.set(key, value),
        hasItem: key => map.has(key),
        length: _ => map.size,
        removeItem: key => map.delete(key),
        clear: _ => map.clear()
    }
}

let storage = createStorage();
storage.setItem('userName', 'Alex');
storage.getItem('userName'); // 'Alex'
console.log(storage.getItem('userName'));

storage.getItem('userAge'); // null
console.log(storage.getItem('userAge'));

storage.hasItem('userAge'); // false
console.log(storage.hasItem('userAge'));

storage.setItem('userAge', 28);
console.log(storage.getItem('userAge'));

storage.hasItem('userAge'); // true
console.log(storage.hasItem('userAge'));

storage.length(); // 2
console.log(storage.length());

storage.removeItem('userName');
console.log(storage.getItem('userName'));

→ Ссылка
Автор решения: wololo

Хоть по функционалу ваш код очень похож нa Map, но в принципе можно некоторый аналог написать и без Map. Как-то так:

function createStorage() {
    let storage = Object.create(null);
    let storageLength = 0;
    
    return {
        setItem(key, value) {
            if ( !(key in storage) )
                ++storageLength;
            storage[key] = value;
            return this;
        },
        getItem(key) {
            if (key in storage)
                return storage[key];
            return null;
        },
        hasItem(key) {
            return key in storage;
        },
        length() {
            return storageLength;
        },
        removeItem(key) {
            if (key in storage) {
                --storageLength;
                delete storage[key];
                return true;
            }
            return false;
        },
        clear() {
            storageLength = 0;
            storage = Object.create(null);
        },
    };
}

let storage = createStorage();
storage.setItem('userName', 'Alex');

console.log( storage.getItem('userName') ); // 'Alex'
console.log( storage.getItem('userAge') ); // null
console.log( storage.hasItem('userAge') ); // false

storage.setItem('userAge', 28);

console.log( storage.hasItem('userAge') ); // true
console.log( storage.length() ); // 2

storage.removeItem('userName');

console.log( storage.length() ); // 1

storage.clear();

console.log( storage.length() ); // 0

Хотя это, конечно же, не полный аналог Map. Ведь у него в качестве свойств могут выступать не только строки и символы.

→ Ссылка
Автор решения: Alia Tempora
function createStorage() {
    let map = new Map();
    return {
        getItem: function (key) { return map.get(key); },
        setItem: function (key) { return map.set(key); },
        hasItem: function (key) { return map.has(key); },
        lenth: function (key) { return map.size(key); },
        removeItem: function(key) { return map.delete(key); },
        clear: function() {return map.clear}
   
    }
}

let storage = createStorage();
storage.setItem('userName', 'Alex');
storage.getItem('userName'); // 'Alex'
storage.getItem('userAge'); // null
storage.hasItem('userAge'); // false
storage.setItem('userAge', 28);
storage.hasItem('userAge'); // true
storage.length(); // 2
storage.removeItem('userName');
storage.length(); // 1
storage.clear();
storage.length(); // 0
→ Ссылка