Echilon
Echilon

Reputation: 10254

JavaScript Closure Scope with two functions

I'm struggling with closure scope in a JavaScrit function. The function below should create three swatches with different images (which works), then when these are clicked, should switch the stylesheet.

The problem is that the same object is passed to the switchTheme function even though stepping through shows the theme variable in the first function does change.

var switcherConfig = {
    themes: 
        {
            'Orangeness': {
                folder: 'ui-lightness'
            },
            'Red Matter': {
                folder: 'blitzer'
            },
            'Flubber': {
                folder: 'south-street'
            }
        }
}
function createThemeSwitcher(placeholderSelector) {
    for (var themeName in switcherConfig.themes) {
        var theme = switcherConfig.themes[themeName];
        var anchor = $('<a/>')
            //.text(theme.title)
            .attr('title', theme.title)
            .attr('href', '#')
            .on('click', function () { switchTheme(theme); })
            // append to DOM etc
    }
}
function switchTheme(theme) {
    var themeDirectory = switcherConfig.baseDirectory + '/' + theme.folder + '/';
    // 'theme' variable is always the last in my 'themes' config object
}

Upvotes: 0

Views: 93

Answers (3)

Viktor S.
Viktor S.

Reputation: 12815

Instead of making closure you can use .data like below (just an alternative):

var switcherConfig = {
    themes: 
        {
            'Orangeness': {
                title:"Orangeness",
                folder: 'ui-lightness'
            },
            'Red Matter': {
                                title:'Red Matter',
                folder: 'blitzer'
            },
            'Flubber': {
                title:'Flubber',
                folder: 'south-street'
            }
        }
}
function createThemeSwitcher(placeholderSelector) {
    for (var themeName in switcherConfig.themes) {
        var theme = switcherConfig.themes[themeName];
        var anchor = $('<a/>')
            .data("theme",theme)
            .attr('title', theme.title)
            .attr('href', '#')
            .html(theme.title)
            .on('click', function () { switchTheme($(this).data("theme")); })
            $("body").append(anchor);
    }
}
function switchTheme(theme) {
    alert(theme.title)
}

Demo

Upvotes: 0

Sebastian.Belczyk
Sebastian.Belczyk

Reputation: 885

Move

var theme = switcherConfig.themes[themeName];

to click function

function createThemeSwitcher(placeholderSelector) {
    for (var themeName in switcherConfig.themes) {

        var anchor = $('<a/>')
            //.text(theme.title)
            .attr('title', theme.title)
            .attr('href', '#')
            .on('click', function () { 
                         var theme = switcherConfig.themes[themeName];
                         switchTheme(theme); 
            })
            // append to DOM etc
    }
}

Upvotes: 0

deceze
deceze

Reputation: 522250

The value used by switchTheme(theme) will be the state that theme is in when the function is called, the value is not bound at the moment you create that anonymous callback. Use a closure to bind that particular value:

.on('click', (function (t) {
    return function () { switchTheme(t); };
})(theme))

Upvotes: 3

Related Questions